forked from CIT/Vmeda.Online
		
	MOBILE-3651 core: Fix scroll to element function
This commit is contained in:
		
							parent
							
								
									1620dd47ea
								
							
						
					
					
						commit
						f682d89e67
					
				@ -47,6 +47,7 @@ export class AddonModQuizPreflightModalComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        formBuilder: FormBuilder,
 | 
			
		||||
        protected elementRef: ElementRef,
 | 
			
		||||
    ) {
 | 
			
		||||
        // Create an empty form group. The controls will be added by the access rules components.
 | 
			
		||||
        this.preflightForm = formBuilder.group({});
 | 
			
		||||
@ -115,7 +116,12 @@ export class AddonModQuizPreflightModalComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
        if (!this.preflightForm.valid) {
 | 
			
		||||
            // Form not valid. Scroll to the first element with errors.
 | 
			
		||||
            if (!CoreDomUtils.instance.scrollToInputError(this.content)) {
 | 
			
		||||
            const hasScrolled = CoreDomUtils.instance.scrollToInputError(
 | 
			
		||||
                this.elementRef.nativeElement,
 | 
			
		||||
                this.content,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            if (!hasScrolled) {
 | 
			
		||||
                // Input not found, show an error modal.
 | 
			
		||||
                CoreDomUtils.instance.showErrorModal('core.errorinvalidform', true);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -681,9 +681,11 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
 | 
			
		||||
     * @param slot Slot of the question to scroll to.
 | 
			
		||||
     */
 | 
			
		||||
    protected scrollToQuestion(slot: number): void {
 | 
			
		||||
        if (this.content) {
 | 
			
		||||
            CoreDomUtils.instance.scrollToElementBySelector(this.content, '#addon-mod_quiz-question-' + slot);
 | 
			
		||||
        }
 | 
			
		||||
        CoreDomUtils.instance.scrollToElementBySelector(
 | 
			
		||||
            this.elementRef.nativeElement,
 | 
			
		||||
            this.content,
 | 
			
		||||
            '#addon-mod_quiz-question-' + slot,
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -104,7 +104,11 @@ export class CoreLinkDirective implements OnInit {
 | 
			
		||||
        if (href.charAt(0) == '#') {
 | 
			
		||||
            // Look for id or name.
 | 
			
		||||
            href = href.substr(1);
 | 
			
		||||
            CoreDomUtils.instance.scrollToElementBySelector(this.content, '#' + href + ', [name=\'' + href + '\']');
 | 
			
		||||
            CoreDomUtils.instance.scrollToElementBySelector(
 | 
			
		||||
                this.element.closest('ion-content'),
 | 
			
		||||
                this.content,
 | 
			
		||||
                `#${href}, [name='${href}']`,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,7 @@ import {
 | 
			
		||||
    QueryList,
 | 
			
		||||
    Type,
 | 
			
		||||
    ViewChild,
 | 
			
		||||
    ElementRef,
 | 
			
		||||
} from '@angular/core';
 | 
			
		||||
 | 
			
		||||
import { CoreSites } from '@services/sites';
 | 
			
		||||
@ -111,6 +112,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        protected content: IonContent,
 | 
			
		||||
        protected elementRef: ElementRef,
 | 
			
		||||
    ) {
 | 
			
		||||
        // Pass this instance to all components so they can use its methods and properties.
 | 
			
		||||
        this.data.coreCourseFormatComponent = this;
 | 
			
		||||
@ -402,7 +404,11 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
 | 
			
		||||
        if (this.moduleId && typeof previousValue == 'undefined') {
 | 
			
		||||
            setTimeout(() => {
 | 
			
		||||
                CoreDomUtils.instance.scrollToElementBySelector(this.content, '#core-course-module-' + this.moduleId);
 | 
			
		||||
                CoreDomUtils.instance.scrollToElementBySelector(
 | 
			
		||||
                    this.elementRef.nativeElement,
 | 
			
		||||
                    this.content,
 | 
			
		||||
                    '#core-course-module-' + this.moduleId,
 | 
			
		||||
                );
 | 
			
		||||
            }, 200);
 | 
			
		||||
        } else {
 | 
			
		||||
            this.content.scrollToTop(0);
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,7 @@
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { Component, ViewChild, ElementRef, OnInit } from '@angular/core';
 | 
			
		||||
import { Component, ViewChild, ElementRef, OnInit, ChangeDetectorRef } from '@angular/core';
 | 
			
		||||
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
 | 
			
		||||
import { IonContent, IonRefresher } from '@ionic/angular';
 | 
			
		||||
 | 
			
		||||
@ -81,6 +81,8 @@ export class CoreLoginEmailSignupPage implements OnInit {
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        protected fb: FormBuilder,
 | 
			
		||||
        protected elementRef: ElementRef,
 | 
			
		||||
        protected changeDetector: ChangeDetectorRef,
 | 
			
		||||
    ) {
 | 
			
		||||
        // Create the ageVerificationForm.
 | 
			
		||||
        this.ageVerificationForm = this.fb.group({
 | 
			
		||||
@ -272,8 +274,17 @@ export class CoreLoginEmailSignupPage implements OnInit {
 | 
			
		||||
        e.stopPropagation();
 | 
			
		||||
 | 
			
		||||
        if (!this.signupForm.valid || (this.settings?.recaptchapublickey && !this.captcha.recaptcharesponse)) {
 | 
			
		||||
            // Form not valid. Scroll to the first element with errors.
 | 
			
		||||
            const errorFound = await CoreDomUtils.instance.scrollToInputError(this.content);
 | 
			
		||||
            // Form not valid. Mark all controls as dirty to display errors.
 | 
			
		||||
            for (const name in this.signupForm.controls) {
 | 
			
		||||
                this.signupForm.controls[name].markAsDirty();
 | 
			
		||||
            }
 | 
			
		||||
            this.changeDetector.detectChanges();
 | 
			
		||||
 | 
			
		||||
            // Scroll to the first element with errors.
 | 
			
		||||
            const errorFound = CoreDomUtils.instance.scrollToInputError(
 | 
			
		||||
                this.elementRef.nativeElement,
 | 
			
		||||
                this.content,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            if (!errorFound) {
 | 
			
		||||
                // Input not found, show an error modal.
 | 
			
		||||
 | 
			
		||||
@ -1119,24 +1119,26 @@ export class CoreDomUtilsProvider {
 | 
			
		||||
    /**
 | 
			
		||||
     * Scroll to a certain element using a selector to find it.
 | 
			
		||||
     *
 | 
			
		||||
     * @param container The element that contains the element that must be scrolled.
 | 
			
		||||
     * @param content The content that must be scrolled.
 | 
			
		||||
     * @param selector Selector to find the element to scroll to.
 | 
			
		||||
     * @param scrollParentClass Parent class where to stop calculating the position. Default inner-scroll.
 | 
			
		||||
     * @param duration Duration of the scroll animation in milliseconds.
 | 
			
		||||
     * @return True if the element is found, false otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    async scrollToElementBySelector(
 | 
			
		||||
        content: IonContent,
 | 
			
		||||
    scrollToElementBySelector(
 | 
			
		||||
        container: HTMLElement | null,
 | 
			
		||||
        content: IonContent | undefined,
 | 
			
		||||
        selector: string,
 | 
			
		||||
        scrollParentClass?: string,
 | 
			
		||||
        duration?: number,
 | 
			
		||||
    ): Promise<boolean> {
 | 
			
		||||
        // @todo: This function is broken. Scroll element cannot be used because it uses shadow DOM so querySelector returns null.
 | 
			
		||||
        // Also, traversing using parentElement doesn't work either, offsetParent isn't part of the parentElement tree.
 | 
			
		||||
        try {
 | 
			
		||||
            const scrollElement = await content.getScrollElement();
 | 
			
		||||
    ): boolean {
 | 
			
		||||
        if (!container || !content) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            const position = this.getElementXY(scrollElement, selector, scrollParentClass);
 | 
			
		||||
        try {
 | 
			
		||||
            const position = this.getElementXY(container, selector, scrollParentClass);
 | 
			
		||||
            if (!position) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
@ -1152,16 +1154,13 @@ export class CoreDomUtilsProvider {
 | 
			
		||||
    /**
 | 
			
		||||
     * Search for an input with error (core-input-error directive) and scrolls to it if found.
 | 
			
		||||
     *
 | 
			
		||||
     * @param container The element that contains the element that must be scrolled.
 | 
			
		||||
     * @param content The content that must be scrolled.
 | 
			
		||||
     * @param scrollParentClass Parent class where to stop calculating the position. Default inner-scroll.
 | 
			
		||||
     * @return True if the element is found, false otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    async scrollToInputError(content?: IonContent, scrollParentClass?: string): Promise<boolean> {
 | 
			
		||||
        if (!content) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this.scrollToElementBySelector(content, '.core-input-error', scrollParentClass);
 | 
			
		||||
    scrollToInputError(container: HTMLElement | null, content?: IonContent, scrollParentClass?: string): boolean {
 | 
			
		||||
        return this.scrollToElementBySelector(container, content, '.core-input-error', scrollParentClass);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user