forked from CIT/Vmeda.Online
		
	MOBILE-3074 format-text: Fix size calculation when content has images
This commit is contained in:
		
							parent
							
								
									1944f46fb5
								
							
						
					
					
						commit
						90f340aaa5
					
				@ -12,7 +12,7 @@
 | 
				
			|||||||
// See the License for the specific language governing permissions and
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
// limitations under the License.
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Directive, Input, AfterViewInit, ElementRef, OnChanges, SimpleChange } from '@angular/core';
 | 
					import { Directive, Input, AfterViewInit, ElementRef, OnChanges, SimpleChange, Output, EventEmitter } from '@angular/core';
 | 
				
			||||||
import { Platform } from 'ionic-angular';
 | 
					import { Platform } from 'ionic-angular';
 | 
				
			||||||
import { CoreAppProvider } from '@providers/app';
 | 
					import { CoreAppProvider } from '@providers/app';
 | 
				
			||||||
import { CoreLoggerProvider } from '@providers/logger';
 | 
					import { CoreLoggerProvider } from '@providers/logger';
 | 
				
			||||||
@ -43,6 +43,7 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
 | 
				
			|||||||
    @Input() href?: string;
 | 
					    @Input() href?: string;
 | 
				
			||||||
    @Input('target-src') targetSrc?: string;
 | 
					    @Input('target-src') targetSrc?: string;
 | 
				
			||||||
    @Input() poster?: string;
 | 
					    @Input() poster?: string;
 | 
				
			||||||
 | 
					    @Output() onLoad = new EventEmitter(); // Emitted when content is loaded. Only for images.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected element: HTMLElement;
 | 
					    protected element: HTMLElement;
 | 
				
			||||||
    protected logger;
 | 
					    protected logger;
 | 
				
			||||||
@ -225,7 +226,17 @@ export class CoreExternalContentDirective implements AfterViewInit, OnChanges {
 | 
				
			|||||||
                    // The browser does not catch changes in SRC, we need to add a new source.
 | 
					                    // The browser does not catch changes in SRC, we need to add a new source.
 | 
				
			||||||
                    this.addSource(finalUrl);
 | 
					                    this.addSource(finalUrl);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
 | 
					                    if (tagName === 'IMG') {
 | 
				
			||||||
 | 
					                        const listener = (): void => {
 | 
				
			||||||
 | 
					                            this.element.removeEventListener('load', listener);
 | 
				
			||||||
 | 
					                            this.element.removeEventListener('error', listener);
 | 
				
			||||||
 | 
					                            this.onLoad.emit();
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					                        this.element.addEventListener('load', listener);
 | 
				
			||||||
 | 
					                        this.element.addEventListener('error', listener);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                    this.element.setAttribute(targetAttr, finalUrl);
 | 
					                    this.element.setAttribute(targetAttr, finalUrl);
 | 
				
			||||||
 | 
					                    this.element.setAttribute('data-original-' + targetAttr, url);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Set events to download big files (not downloaded automatically).
 | 
					                // Set events to download big files (not downloaded automatically).
 | 
				
			||||||
 | 
				
			|||||||
@ -90,8 +90,9 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
     * Apply CoreExternalContentDirective to a certain element.
 | 
					     * Apply CoreExternalContentDirective to a certain element.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param {HTMLElement} element Element to add the attributes to.
 | 
					     * @param {HTMLElement} element Element to add the attributes to.
 | 
				
			||||||
 | 
					     * @return {CoreExternalContentDirective} External content instance.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected addExternalContent(element: HTMLElement): void {
 | 
					    protected addExternalContent(element: HTMLElement): CoreExternalContentDirective {
 | 
				
			||||||
        // Angular 2 doesn't let adding directives dynamically. Create the CoreExternalContentDirective manually.
 | 
					        // Angular 2 doesn't let adding directives dynamically. Create the CoreExternalContentDirective manually.
 | 
				
			||||||
        const extContent = new CoreExternalContentDirective(<any> element, this.loggerProvider, this.filepoolProvider,
 | 
					        const extContent = new CoreExternalContentDirective(<any> element, this.loggerProvider, this.filepoolProvider,
 | 
				
			||||||
            this.platform, this.sitesProvider, this.domUtils, this.urlUtils, this.appProvider, this.utils);
 | 
					            this.platform, this.sitesProvider, this.domUtils, this.urlUtils, this.appProvider, this.utils);
 | 
				
			||||||
@ -105,6 +106,8 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
        extContent.poster = element.getAttribute('poster');
 | 
					        extContent.poster = element.getAttribute('poster');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        extContent.ngAfterViewInit();
 | 
					        extContent.ngAfterViewInit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return extContent;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -117,15 +120,13 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Wrap an image with a container to adapt its width and, if needed, add an anchor to view it in full size.
 | 
					     * Wrap an image with a container to adapt its width.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param {number} elWidth Width of the directive's element.
 | 
					 | 
				
			||||||
     * @param {HTMLElement} img Image to adapt.
 | 
					     * @param {HTMLElement} img Image to adapt.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected adaptImage(elWidth: number, img: HTMLElement): void {
 | 
					    protected adaptImage(img: HTMLElement): void {
 | 
				
			||||||
        const imgWidth = this.getElementWidth(img),
 | 
					        // Element to wrap the image.
 | 
				
			||||||
            // Element to wrap the image.
 | 
					        const container = document.createElement('span'),
 | 
				
			||||||
            container = document.createElement('span'),
 | 
					 | 
				
			||||||
            originalWidth = img.attributes.getNamedItem('width');
 | 
					            originalWidth = img.attributes.getNamedItem('width');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const forcedWidth = parseInt(originalWidth && originalWidth.value);
 | 
					        const forcedWidth = parseInt(originalWidth && originalWidth.value);
 | 
				
			||||||
@ -152,36 +153,48 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.domUtils.wrapElement(img, container);
 | 
					        this.domUtils.wrapElement(img, container);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (imgWidth > elWidth) {
 | 
					 | 
				
			||||||
            // The image has been adapted, add an anchor to view it in full size.
 | 
					 | 
				
			||||||
            this.addMagnifyingGlass(container, img);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Add a magnifying glass icon to view an image at full size.
 | 
					     * Add magnifying glass icons to view adapted images at full size.
 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * @param {HTMLElement} container The container of the image.
 | 
					 | 
				
			||||||
     * @param {HTMLElement} img The image.
 | 
					 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    addMagnifyingGlass(container: HTMLElement, img: HTMLElement): void {
 | 
					    addMagnifyingGlasses(): void {
 | 
				
			||||||
        const imgSrc = this.textUtils.escapeHTML(img.getAttribute('src')),
 | 
					        const imgs = Array.from(this.element.querySelectorAll('.core-adapted-img-container > img'));
 | 
				
			||||||
 | 
					        if (!imgs.length) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // If cannot calculate element's width, use viewport width to avoid false adapt image icons appearing.
 | 
				
			||||||
 | 
					        const elWidth = this.getElementWidth(this.element) || window.innerWidth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        imgs.forEach((img: HTMLImageElement) => {
 | 
				
			||||||
 | 
					            let imgWidth = parseInt(img.getAttribute('width'));
 | 
				
			||||||
 | 
					            if (!imgWidth) {
 | 
				
			||||||
 | 
					                // No width attribute, use real size.
 | 
				
			||||||
 | 
					                imgWidth = img.naturalWidth;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (imgWidth <= elWidth) {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const imgSrc = this.textUtils.escapeHTML(img.getAttribute('data-original-src') || img.getAttribute('src')),
 | 
				
			||||||
            label = this.textUtils.escapeHTML(this.translate.instant('core.openfullimage')),
 | 
					            label = this.textUtils.escapeHTML(this.translate.instant('core.openfullimage')),
 | 
				
			||||||
            anchor = document.createElement('a');
 | 
					            anchor = document.createElement('a');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        anchor.classList.add('core-image-viewer-icon');
 | 
					            anchor.classList.add('core-image-viewer-icon');
 | 
				
			||||||
        anchor.setAttribute('aria-label', label);
 | 
					            anchor.setAttribute('aria-label', label);
 | 
				
			||||||
        // Add an ion-icon item to apply the right styles, but the ion-icon component won't be executed.
 | 
					            // Add an ion-icon item to apply the right styles, but the ion-icon component won't be executed.
 | 
				
			||||||
        anchor.innerHTML = '<ion-icon name="search" class="icon icon-md ion-md-search"></ion-icon>';
 | 
					            anchor.innerHTML = '<ion-icon name="search" class="icon icon-md ion-md-search"></ion-icon>';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        anchor.addEventListener('click', (e: Event) => {
 | 
					            anchor.addEventListener('click', (e: Event) => {
 | 
				
			||||||
            e.preventDefault();
 | 
					                e.preventDefault();
 | 
				
			||||||
            e.stopPropagation();
 | 
					                e.stopPropagation();
 | 
				
			||||||
            this.domUtils.viewImage(imgSrc, img.getAttribute('alt'), this.component, this.componentId);
 | 
					                this.domUtils.viewImage(imgSrc, img.getAttribute('alt'), this.component, this.componentId);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            img.parentNode.appendChild(anchor);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					 | 
				
			||||||
        container.appendChild(anchor);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -307,12 +320,8 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
                // Calculate the height now.
 | 
					                // Calculate the height now.
 | 
				
			||||||
                this.calculateHeight();
 | 
					                this.calculateHeight();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Wait for images to load and calculate the height again if needed.
 | 
					                // Add magnifying glasses to images.
 | 
				
			||||||
                this.domUtils.waitForImages(this.element).then((hasImgToLoad) => {
 | 
					                this.addMagnifyingGlasses();
 | 
				
			||||||
                    if (hasImgToLoad) {
 | 
					 | 
				
			||||||
                        this.calculateHeight();
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (!this.loadingChangedListener) {
 | 
					                if (!this.loadingChangedListener) {
 | 
				
			||||||
                    // Recalculate the height if a parent core-loading displays the content.
 | 
					                    // Recalculate the height if a parent core-loading displays the content.
 | 
				
			||||||
@ -387,16 +396,14 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
                this.addExternalContent(anchor);
 | 
					                this.addExternalContent(anchor);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const externalImages: CoreExternalContentDirective[] = [];
 | 
				
			||||||
            if (images && images.length > 0) {
 | 
					            if (images && images.length > 0) {
 | 
				
			||||||
                // If cannot calculate element's width, use a medium number to avoid false adapt image icons appearing.
 | 
					 | 
				
			||||||
                const elWidth = this.getElementWidth(this.element) || 100;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                // Walk through the content to find images, and add our directive.
 | 
					                // Walk through the content to find images, and add our directive.
 | 
				
			||||||
                images.forEach((img: HTMLElement) => {
 | 
					                images.forEach((img: HTMLElement) => {
 | 
				
			||||||
                    this.addMediaAdaptClass(img);
 | 
					                    this.addMediaAdaptClass(img);
 | 
				
			||||||
                    this.addExternalContent(img);
 | 
					                    externalImages.push(this.addExternalContent(img));
 | 
				
			||||||
                    if (this.utils.isTrueOrOne(this.adaptImg) && !img.classList.contains('icon')) {
 | 
					                    if (this.utils.isTrueOrOne(this.adaptImg) && !img.classList.contains('icon')) {
 | 
				
			||||||
                        this.adaptImage(elWidth, img);
 | 
					                        this.adaptImage(img);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -445,7 +452,24 @@ export class CoreFormatTextDirective implements OnChanges {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            this.domUtils.handleBootstrapTooltips(div);
 | 
					            this.domUtils.handleBootstrapTooltips(div);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return div;
 | 
					            // Wait for images to load.
 | 
				
			||||||
 | 
					            let promise: Promise<any> = null;
 | 
				
			||||||
 | 
					            if (externalImages.length) {
 | 
				
			||||||
 | 
					                promise = Promise.all(externalImages.map((externalImage) => {
 | 
				
			||||||
 | 
					                    return new Promise((resolve): void => {
 | 
				
			||||||
 | 
					                        const subscription = externalImage.onLoad.subscribe(() => {
 | 
				
			||||||
 | 
					                            subscription.unsubscribe();
 | 
				
			||||||
 | 
					                            resolve();
 | 
				
			||||||
 | 
					                        });
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                }));
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                promise = Promise.resolve();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return promise.then(() => {
 | 
				
			||||||
 | 
					                return div;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user