UNPKG

custom-lightbox

Version:

custom-lightbox

514 lines 25.9 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); var core_1 = require("@angular/core"); var platform_browser_1 = require("@angular/platform-browser"); var lightbox_event_service_1 = require("./lightbox-event.service"); var LightboxComponent = /** @class */ (function () { function LightboxComponent(_elemRef, _rendererRef, _lightboxEvent, _lightboxElem, _lightboxWindowRef, _sanitizer) { var _this = this; this._elemRef = _elemRef; this._rendererRef = _rendererRef; this._lightboxEvent = _lightboxEvent; this._lightboxElem = _lightboxElem; this._lightboxWindowRef = _lightboxWindowRef; this._sanitizer = _sanitizer; // initialize data this.options = this.options || {}; this.album = this.album || []; this.currentImageIndex = this.currentImageIndex || 0; this._windowRef = this._lightboxWindowRef.nativeWindow; // control the interactive of the directive this.ui = { // control the appear of the reloader // false: image has loaded completely and ready to be shown // true: image is still loading showReloader: true, // control the appear of the nav arrow // the arrowNav is the parent of both left and right arrow // in some cases, the parent shows but the child does not show showLeftArrow: false, showRightArrow: false, showArrowNav: false, // control whether to show the // page number or not showPageNumber: false, showCaption: false, classList: 'lightbox animation fadeIn' }; this.content = { pageNumber: '' }; this._event = {}; this._lightboxElem = this._elemRef; this._event.subscription = this._lightboxEvent.lightboxEvent$ .subscribe(function (event) { return _this._onReceivedEvent(event); }); this._documentRef = window.document; } LightboxComponent.prototype.ngOnInit = function () { var _this = this; this.album.forEach(function (album) { if (album.caption) { album.caption = _this._sanitizer.sanitize(core_1.SecurityContext.HTML, album.caption); } }); }; LightboxComponent.prototype.ngAfterViewInit = function () { // need to init css value here, after the view ready // actually these values are always 0 this._cssValue = { containerTopPadding: Math.round(this._getCssStyleValue(this._containerElem, 'padding-top')), containerRightPadding: Math.round(this._getCssStyleValue(this._containerElem, 'padding-right')), containerBottomPadding: Math.round(this._getCssStyleValue(this._containerElem, 'padding-bottom')), containerLeftPadding: Math.round(this._getCssStyleValue(this._containerElem, 'padding-left')), imageBorderWidthTop: Math.round(this._getCssStyleValue(this._imageElem, 'border-top-width')), imageBorderWidthBottom: Math.round(this._getCssStyleValue(this._imageElem, 'border-bottom-width')), imageBorderWidthLeft: Math.round(this._getCssStyleValue(this._imageElem, 'border-left-width')), imageBorderWidthRight: Math.round(this._getCssStyleValue(this._imageElem, 'border-right-width')) }; if (this._validateInputData()) { this._prepareComponent(); this._registerImageLoadingEvent(); } }; LightboxComponent.prototype.ngOnDestroy = function () { if (!this.options.disableKeyboardNav) { // unbind keyboard event this._disableKeyboardNav(); } this._event.subscription.unsubscribe(); }; LightboxComponent.prototype.close = function ($event) { $event.stopPropagation(); if ($event.target.classList.contains('lightbox') || $event.target.classList.contains('lb-loader') || $event.target.classList.contains('lb-close')) { this._lightboxEvent.broadcastLightboxEvent({ id: lightbox_event_service_1.LIGHTBOX_EVENT.CLOSE, data: null }); } }; LightboxComponent.prototype.nextImage = function () { if (this.album.length === 1) { return; } else if (this.currentImageIndex === this.album.length - 1) { this._changeImage(0); } else { this._changeImage(this.currentImageIndex + 1); } }; LightboxComponent.prototype.prevImage = function () { if (this.album.length === 1) { return; } else if (this.currentImageIndex === 0 && this.album.length > 1) { this._changeImage(this.album.length - 1); } else { this._changeImage(this.currentImageIndex - 1); } }; LightboxComponent.prototype._validateInputData = function () { if (this.album && this.album instanceof Array && this.album.length > 0) { for (var i = 0; i < this.album.length; i++) { // check whether each _nside // album has src data or not if (this.album[i].src) { continue; } throw new Error('One of the album data does not have source data'); } } else { throw new Error('No album data or album data is not correct in type'); } // to prevent data understand as string // convert it to number if (isNaN(this.currentImageIndex)) { throw new Error('Current image index is not a number'); } else { this.currentImageIndex = Number(this.currentImageIndex); } return true; }; LightboxComponent.prototype._registerImageLoadingEvent = function () { var _this = this; var preloader = new Image(); preloader.onload = function () { _this._onLoadImageSuccess(); }; var src = this.album[this.currentImageIndex].src; preloader.src = this._sanitizer.sanitize(core_1.SecurityContext.URL, src); }; /** * Fire when the image is loaded */ LightboxComponent.prototype._onLoadImageSuccess = function () { if (!this.options.disableKeyboardNav) { // unbind keyboard event during transition this._disableKeyboardNav(); } var imageHeight; var imageWidth; var maxImageHeight; var maxImageWidth; var windowHeight; var windowWidth; var naturalImageWidth; var naturalImageHeight; // set default width and height of image to be its natural imageWidth = naturalImageWidth = this._imageElem.nativeElement.naturalWidth; imageHeight = naturalImageHeight = this._imageElem.nativeElement.naturalHeight; if (this.options.fitImageInViewPort) { windowWidth = this._windowRef.innerWidth; windowHeight = this._windowRef.innerHeight; maxImageWidth = windowWidth - this._cssValue.containerLeftPadding - this._cssValue.containerRightPadding - this._cssValue.imageBorderWidthLeft - this._cssValue.imageBorderWidthRight - 20; maxImageHeight = windowHeight - this._cssValue.containerTopPadding - this._cssValue.containerTopPadding - this._cssValue.imageBorderWidthTop - this._cssValue.imageBorderWidthBottom - 120; if (naturalImageWidth > maxImageWidth || naturalImageHeight > maxImageHeight) { if ((naturalImageWidth / maxImageWidth) > (naturalImageHeight / maxImageHeight)) { imageWidth = maxImageWidth; imageHeight = Math.round(naturalImageHeight / (naturalImageWidth / imageWidth)); } else { imageHeight = maxImageHeight; imageWidth = Math.round(naturalImageWidth / (naturalImageHeight / imageHeight)); } } this._rendererRef.setStyle(this._imageElem.nativeElement, 'width', imageWidth + "px"); this._rendererRef.setStyle(this._imageElem.nativeElement, 'height', imageHeight + "px"); } this._sizeContainer(imageWidth, imageHeight); if (this.options.centerVertically) { this._centerVertically(imageWidth, imageHeight); } }; LightboxComponent.prototype._centerVertically = function (imageWidth, imageHeight) { var scrollOffset = this._documentRef.documentElement.scrollTop; var windowHeight = this._windowRef.innerHeight; var viewOffset = windowHeight / 2 - imageHeight / 2; var topDistance = scrollOffset + viewOffset; this._rendererRef.setStyle(this._lightboxElem.nativeElement, 'top', topDistance + "px"); }; LightboxComponent.prototype._sizeContainer = function (imageWidth, imageHeight) { var _this = this; var oldWidth = this._outerContainerElem.nativeElement.offsetWidth; var oldHeight = this._outerContainerElem.nativeElement.offsetHeight; var newWidth = imageWidth + this._cssValue.containerRightPadding + this._cssValue.containerLeftPadding + this._cssValue.imageBorderWidthLeft + this._cssValue.imageBorderWidthRight; var newHeight = imageHeight + this._cssValue.containerTopPadding + this._cssValue.containerBottomPadding + this._cssValue.imageBorderWidthTop + this._cssValue.imageBorderWidthBottom; if (oldWidth !== newWidth || oldHeight !== newHeight) { this._rendererRef.setStyle(this._outerContainerElem.nativeElement, 'width', newWidth + "px"); this._rendererRef.setStyle(this._outerContainerElem.nativeElement, 'height', newHeight + "px"); // bind resize event to outer container // use enableTransition to prevent infinite loader if (this.options.enableTransition) { this._event.transitions = []; ['transitionend', 'webkitTransitionEnd', 'oTransitionEnd', 'MSTransitionEnd'].forEach(function (eventName) { _this._event.transitions.push(_this._rendererRef.listen(_this._outerContainerElem.nativeElement, eventName, function (event) { if (event.target === event.currentTarget) { _this._postResize(newWidth, newHeight); } })); }); } else { this._postResize(newWidth, newHeight); } } else { this._postResize(newWidth, newHeight); } }; LightboxComponent.prototype._postResize = function (newWidth, newHeight) { // unbind resize event if (Array.isArray(this._event.transitions)) { this._event.transitions.forEach(function (eventHandler) { eventHandler(); }); this._event.transitions = []; } this._rendererRef.setStyle(this._dataContainerElem.nativeElement, 'width', newWidth + "px"); this._showImage(); }; LightboxComponent.prototype._showImage = function () { this.ui.showReloader = false; this._updateNav(); this._updateDetails(); if (!this.options.disableKeyboardNav) { this._enableKeyboardNav(); } }; LightboxComponent.prototype._prepareComponent = function () { // add css3 animation this._addCssAnimation(); // position the image according to user's option this._positionLightBox(); }; LightboxComponent.prototype._positionLightBox = function () { // @see https://stackoverflow.com/questions/3464876/javascript-get-window-x-y-position-for-scroll var top = (this._windowRef.pageYOffset || this._documentRef.documentElement.scrollTop) + this.options.positionFromTop; var left = this._windowRef.pageXOffset || this._documentRef.documentElement.scrollLeft; if (!this.options.centerVertically) { this._rendererRef.setStyle(this._lightboxElem.nativeElement, 'top', top + "px"); } this._rendererRef.setStyle(this._lightboxElem.nativeElement, 'left', left + "px"); this._rendererRef.setStyle(this._lightboxElem.nativeElement, 'display', 'block'); // disable scrolling of the page while open if (this.options.disableScrolling) { this._rendererRef.addClass(this._documentRef.documentElement, 'lb-disable-scrolling'); } }; /** * addCssAnimation add css3 classes for animate lightbox */ LightboxComponent.prototype._addCssAnimation = function () { var resizeDuration = this.options.resizeDuration; var fadeDuration = this.options.fadeDuration; this._rendererRef.setStyle(this._lightboxElem.nativeElement, '-webkit-animation-duration', fadeDuration + "s"); this._rendererRef.setStyle(this._lightboxElem.nativeElement, 'animation-duration', fadeDuration + "s"); this._rendererRef.setStyle(this._outerContainerElem.nativeElement, '-webkit-transition-duration', resizeDuration + "s"); this._rendererRef.setStyle(this._outerContainerElem.nativeElement, 'transition-duration', resizeDuration + "s"); this._rendererRef.setStyle(this._dataContainerElem.nativeElement, '-webkit-animation-duration', fadeDuration + "s"); this._rendererRef.setStyle(this._dataContainerElem.nativeElement, 'animation-duration', fadeDuration + "s"); this._rendererRef.setStyle(this._imageElem.nativeElement, '-webkit-animation-duration', fadeDuration + "s"); this._rendererRef.setStyle(this._imageElem.nativeElement, 'animation-duration', fadeDuration + "s"); this._rendererRef.setStyle(this._captionElem.nativeElement, '-webkit-animation-duration', fadeDuration + "s"); this._rendererRef.setStyle(this._captionElem.nativeElement, 'animation-duration', fadeDuration + "s"); this._rendererRef.setStyle(this._numberElem.nativeElement, '-webkit-animation-duration', fadeDuration + "s"); this._rendererRef.setStyle(this._numberElem.nativeElement, 'animation-duration', fadeDuration + "s"); }; LightboxComponent.prototype._end = function () { var _this = this; this.ui.classList = 'lightbox animation fadeOut'; if (this.options.disableScrolling) { this._rendererRef.removeClass(this._documentRef.documentElement, 'lb-disable-scrolling'); } setTimeout(function () { _this.cmpRef.destroy(); }, this.options.fadeDuration * 1000); }; LightboxComponent.prototype._updateDetails = function () { // update the caption if (typeof this.album[this.currentImageIndex].caption !== 'undefined' && this.album[this.currentImageIndex].caption !== '') { this.ui.showCaption = true; } // update the page number if user choose to do so // does not perform numbering the page if the // array length in album <= 1 if (this.album.length > 1 && this.options.showImageNumberLabel) { this.ui.showPageNumber = true; this.content.pageNumber = this._albumLabel(); } }; LightboxComponent.prototype._albumLabel = function () { // due to {this.currentImageIndex} is set from 0 to {this.album.length} - 1 return this.options.albumLabel.replace(/%1/g, Number(this.currentImageIndex + 1)).replace(/%2/g, this.album.length); }; LightboxComponent.prototype._changeImage = function (newIndex) { this.currentImageIndex = newIndex; this._hideImage(); this._registerImageLoadingEvent(); this._lightboxEvent.broadcastLightboxEvent({ id: lightbox_event_service_1.LIGHTBOX_EVENT.CHANGE_PAGE, data: newIndex }); }; LightboxComponent.prototype._hideImage = function () { this.ui.showReloader = true; this.ui.showArrowNav = false; this.ui.showLeftArrow = false; this.ui.showRightArrow = false; this.ui.showPageNumber = false; this.ui.showCaption = false; }; LightboxComponent.prototype._updateNav = function () { var alwaysShowNav = false; // check to see the browser support touch event try { this._documentRef.createEvent('TouchEvent'); alwaysShowNav = (this.options.alwaysShowNavOnTouchDevices) ? true : false; } catch (e) { // noop } // initially show the arrow nav // which is the parent of both left and right nav this._showArrowNav(); if (this.album.length > 1) { if (this.options.wrapAround) { if (alwaysShowNav) { // alternatives this.$lightbox.find('.lb-prev, .lb-next').css('opacity', '1'); this._rendererRef.setStyle(this._leftArrowElem.nativeElement, 'opacity', '1'); this._rendererRef.setStyle(this._rightArrowElem.nativeElement, 'opacity', '1'); } // alternatives this.$lightbox.find('.lb-prev, .lb-next').show(); this._showLeftArrowNav(); this._showRightArrowNav(); } else { if (this.currentImageIndex > 0) { // alternatives this.$lightbox.find('.lb-prev').show(); this._showLeftArrowNav(); if (alwaysShowNav) { // alternatives this.$lightbox.find('.lb-prev').css('opacity', '1'); this._rendererRef.setStyle(this._leftArrowElem.nativeElement, 'opacity', '1'); } } if (this.currentImageIndex < this.album.length - 1) { // alternatives this.$lightbox.find('.lb-next').show(); this._showRightArrowNav(); if (alwaysShowNav) { // alternatives this.$lightbox.find('.lb-next').css('opacity', '1'); this._rendererRef.setStyle(this._rightArrowElem.nativeElement, 'opacity', '1'); } } } } }; LightboxComponent.prototype._showLeftArrowNav = function () { this.ui.showLeftArrow = true; }; LightboxComponent.prototype._showRightArrowNav = function () { this.ui.showRightArrow = true; }; LightboxComponent.prototype._showArrowNav = function () { this.ui.showArrowNav = (this.album.length !== 1); }; LightboxComponent.prototype._enableKeyboardNav = function () { var _this = this; this._event.keyup = this._rendererRef.listen('document', 'keyup', function (event) { _this._keyboardAction(event); }); }; LightboxComponent.prototype._disableKeyboardNav = function () { if (this._event.keyup) { this._event.keyup(); } }; LightboxComponent.prototype._keyboardAction = function ($event) { var KEYCODE_ESC = 27; var KEYCODE_LEFTARROW = 37; var KEYCODE_RIGHTARROW = 39; var keycode = $event.keyCode; var key = String.fromCharCode(keycode).toLowerCase(); if (keycode === KEYCODE_ESC || key.match(/x|o|c/)) { this._lightboxEvent.broadcastLightboxEvent({ id: lightbox_event_service_1.LIGHTBOX_EVENT.CLOSE, data: null }); } else if (key === 'p' || keycode === KEYCODE_LEFTARROW) { if (this.currentImageIndex !== 0) { this._changeImage(this.currentImageIndex - 1); } else if (this.options.wrapAround && this.album.length > 1) { this._changeImage(this.album.length - 1); } } else if (key === 'n' || keycode === KEYCODE_RIGHTARROW) { if (this.currentImageIndex !== this.album.length - 1) { this._changeImage(this.currentImageIndex + 1); } else if (this.options.wrapAround && this.album.length > 1) { this._changeImage(0); } } }; LightboxComponent.prototype._getCssStyleValue = function (elem, propertyName) { return parseFloat(this._windowRef .getComputedStyle(elem.nativeElement, null) .getPropertyValue(propertyName)); }; LightboxComponent.prototype._onReceivedEvent = function (event) { switch (event.id) { case lightbox_event_service_1.LIGHTBOX_EVENT.CLOSE: this._end(); break; default: break; } }; __decorate([ core_1.Input(), __metadata("design:type", Array) ], LightboxComponent.prototype, "album", void 0); __decorate([ core_1.Input(), __metadata("design:type", Number) ], LightboxComponent.prototype, "currentImageIndex", void 0); __decorate([ core_1.Input(), __metadata("design:type", Object) ], LightboxComponent.prototype, "options", void 0); __decorate([ core_1.Input(), __metadata("design:type", Object) ], LightboxComponent.prototype, "cmpRef", void 0); __decorate([ core_1.ViewChild('outerContainer', { static: false }), __metadata("design:type", core_1.ElementRef) ], LightboxComponent.prototype, "_outerContainerElem", void 0); __decorate([ core_1.ViewChild('container', { static: false }), __metadata("design:type", core_1.ElementRef) ], LightboxComponent.prototype, "_containerElem", void 0); __decorate([ core_1.ViewChild('leftArrow', { static: false }), __metadata("design:type", core_1.ElementRef) ], LightboxComponent.prototype, "_leftArrowElem", void 0); __decorate([ core_1.ViewChild('rightArrow', { static: false }), __metadata("design:type", core_1.ElementRef) ], LightboxComponent.prototype, "_rightArrowElem", void 0); __decorate([ core_1.ViewChild('navArrow', { static: false }), __metadata("design:type", core_1.ElementRef) ], LightboxComponent.prototype, "_navArrowElem", void 0); __decorate([ core_1.ViewChild('dataContainer', { static: false }), __metadata("design:type", core_1.ElementRef) ], LightboxComponent.prototype, "_dataContainerElem", void 0); __decorate([ core_1.ViewChild('image', { static: false }), __metadata("design:type", core_1.ElementRef) ], LightboxComponent.prototype, "_imageElem", void 0); __decorate([ core_1.ViewChild('caption', { static: false }), __metadata("design:type", core_1.ElementRef) ], LightboxComponent.prototype, "_captionElem", void 0); __decorate([ core_1.ViewChild('number', { static: false }), __metadata("design:type", core_1.ElementRef) ], LightboxComponent.prototype, "_numberElem", void 0); LightboxComponent = __decorate([ core_1.Component({ template: "\n <div class=\"lb-outerContainer transition\" #outerContainer>\n <div class=\"lb-container\" #container>\n <img class=\"lb-image\" [src]=\"album[currentImageIndex].src\" class=\"lb-image animation fadeIn\" [hidden]=\"ui.showReloader\" #image>\n <div class=\"lb-nav\" [hidden]=\"!ui.showArrowNav\" #navArrow>\n <a class=\"lb-prev\" [hidden]=\"!ui.showLeftArrow\" (click)=\"prevImage()\" #leftArrow></a>\n <a class=\"lb-next\"[hidden]=\"!ui.showRightArrow\" (click)=\"nextImage()\" #rightArrow></a>\n </div>\n <div class=\"lb-loader\" [hidden]=\"!ui.showReloader\" (click)=\"close($event)\">\n <a class=\"lb-cancel\"></a>\n </div>\n </div>\n </div>\n <div class=\"lb-dataContainer\" [hidden]=\"ui.showReloader\" #dataContainer>\n <div class=\"lb-data\">\n <div class=\"lb-details\">\n <span class=\"lb-caption animation fadeIn\" [hidden]=\"!ui.showCaption\" [innerHtml]=\"album[currentImageIndex].caption\" #caption>\n </span>\n <span class=\"lb-number animation fadeIn\" [hidden]=\"!ui.showPageNumber\" #number>{{ content.pageNumber }}</span>\n </div>\n <div class=\"lb-closeContainer\">\n <a class=\"lb-close\" (click)=\"close($event)\"></a>\n </div>\n </div>\n </div>", selector: '[lb-content]', host: { '(click)': 'close($event)', '[class]': 'ui.classList' } }), __metadata("design:paramtypes", [core_1.ElementRef, core_1.Renderer2, lightbox_event_service_1.LightboxEvent, core_1.ElementRef, lightbox_event_service_1.LightboxWindowRef, platform_browser_1.DomSanitizer]) ], LightboxComponent); return LightboxComponent; }()); exports.LightboxComponent = LightboxComponent; //# sourceMappingURL=lightbox.component.js.map