UNPKG

ngm-masonry

Version:

Angular Module for displaying a feed of items in a masonry layout using https://github.com/glebmlk/ngx-masonry

287 lines (279 loc) 9 kB
import { isPlatformBrowser } from '@angular/common'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Inject, Input, NgZone, Output, PLATFORM_ID, Directive, forwardRef, NgModule } from '@angular/core'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ let imagesLoaded; /** @type {?} */ let masonryConstructor; class NgmMasonryComponent { /** * @param {?} platformId * @param {?} element * @param {?} ngZone * @param {?} changeDetectorRef */ constructor(platformId, element, ngZone, changeDetectorRef) { this.platformId = platformId; this.element = element; this.ngZone = ngZone; this.changeDetectorRef = changeDetectorRef; // Inputs this.options = {}; this.useImagesLoaded = false; this.updateLayout = false; // Outputs this.layoutComplete = new EventEmitter(); this.removeComplete = new EventEmitter(); } /** * @return {?} */ ngOnInit() { this.ngZone.runOutsideAngular(() => { if (this.useImagesLoaded && imagesLoaded === undefined) { imagesLoaded = require('imagesloaded'); } if (isPlatformBrowser(this.platformId) && masonryConstructor === undefined) { masonryConstructor = require('masonry-layout'); } // Create masonry options object if (!this.options) { this.options = {}; } // Set default itemSelector if (!this.options.itemSelector) { this.options.itemSelector = '[ngmMasonryItem], ngmMasonryItem'; } if (isPlatformBrowser(this.platformId)) { // Initialize Masonry this._msnry = new masonryConstructor(this.element.nativeElement, this.options); // Bind to events this._msnry.on('layoutComplete', (items) => { this.layoutComplete.emit(items); this.changeDetectorRef.markForCheck(); }); this._msnry.on('removeComplete', (items) => { this.removeComplete.emit(items); this.changeDetectorRef.markForCheck(); }); } }); } /** * @param {?} changes * @return {?} */ ngOnChanges(changes) { // only update layout if it's not the first change if (changes.updateLayout) { if (!changes.updateLayout.firstChange) { this.layout(); } } } /** * @return {?} */ ngOnDestroy() { if (this._msnry) { this._msnry.destroy(); } } /** * @return {?} */ layout() { requestAnimationFrame(() => { this._msnry.layout(); this.changeDetectorRef.markForCheck(); }); } /** * @return {?} */ reloadItems() { requestAnimationFrame(() => { this._msnry.reloadItems(); this.changeDetectorRef.markForCheck(); }); } // public add(element: HTMLElement, prepend: boolean = false) { /** * @param {?} element * @return {?} */ add(element) { this.ngZone.runOutsideAngular(() => { /** @type {?} */ let isFirstItem = false; // Check if first item if (this._msnry.items.length === 0) { isFirstItem = true; } if (this.useImagesLoaded) { imagesLoaded(element, (instance) => { this.element.nativeElement.appendChild(element); // Tell Masonry that a child element has been added setTimeout(() => { this._msnry.appended(element); this.changeDetectorRef.markForCheck(); }); // layout if first item if (isFirstItem) { this.layout(); } }); this.element.nativeElement.removeChild(element); } else { // Tell Masonry that a child element has been added setTimeout(() => { this._msnry.appended(element); this.changeDetectorRef.markForCheck(); }); // layout if first item if (isFirstItem) { this.layout(); } } }); } /** * @param {?} element * @return {?} */ remove(element) { // Tell Masonry that a child element has been removed this._msnry.remove(element); // Layout items this.layout(); } } NgmMasonryComponent.decorators = [ { type: Component, args: [{ selector: '[ngm-masonry], ngm-masonry', template: '<ng-content></ng-content>', changeDetection: ChangeDetectionStrategy.OnPush, styles: [` :host { display: block; } `] }] } ]; /** @nocollapse */ NgmMasonryComponent.ctorParameters = () => [ { type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] }, { type: ElementRef }, { type: NgZone }, { type: ChangeDetectorRef } ]; NgmMasonryComponent.propDecorators = { options: [{ type: Input }], useImagesLoaded: [{ type: Input }], updateLayout: [{ type: Input }], layoutComplete: [{ type: Output }], removeComplete: [{ type: Output }] }; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class NgmMasonryDirective { /** * @param {?} _element * @param {?} _parent * @param {?} platformId */ constructor(_element, _parent, platformId) { this._element = _element; this._parent = _parent; this.platformId = platformId; } /** * @return {?} */ ngAfterViewInit() { if (isPlatformBrowser(this.platformId)) { this._parent.add(this._element.nativeElement); this.watchForHtmlChanges(); } } /** * @return {?} */ ngOnDestroy() { if (isPlatformBrowser(this.platformId)) { this._parent.remove(this._element.nativeElement); if (!!this._observer) { this._observer.disconnect(); } } } /** * When HTML in brick changes dynamically, observe that and change layout * @private * @return {?} */ watchForHtmlChanges() { MutationObserver = window.MutationObserver || window.WebKitMutationObserver; if (MutationObserver) { this._observer = new MutationObserver(() => { requestAnimationFrame(() => { this._parent.layout(); }); }); } if (!!this._observer) { // define what element should be observed by the observer // and what types of mutations trigger the callback this._observer.observe(this._element.nativeElement, { subtree: true, childList: true, attributes: true, attributeFilter: ['src'], }); } } } NgmMasonryDirective.decorators = [ { type: Directive, args: [{ selector: '[ngmMasonryItem], ngmMasonryItem', },] } ]; /** @nocollapse */ NgmMasonryDirective.ctorParameters = () => [ { type: ElementRef }, { type: NgmMasonryComponent, decorators: [{ type: Inject, args: [forwardRef(() => NgmMasonryComponent),] }] }, { type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class NgmMasonryModule { } NgmMasonryModule.decorators = [ { type: NgModule, args: [{ imports: [], declarations: [NgmMasonryComponent, NgmMasonryDirective], exports: [NgmMasonryComponent, NgmMasonryDirective], },] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ export { NgmMasonryComponent, NgmMasonryDirective, NgmMasonryModule }; //# sourceMappingURL=ngm-masonry.js.map