MOBILE-3814 dom: Fix scroll to element with selector
parent
be28e1c2e4
commit
ac5e4b1d79
|
@ -514,6 +514,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
CoreDomUtils.scrollViewToElement(
|
CoreDomUtils.scrollViewToElement(
|
||||||
this.elementRef.nativeElement,
|
this.elementRef.nativeElement,
|
||||||
'#core-course-module-' + moduleId,
|
'#core-course-module-' + moduleId,
|
||||||
|
{ addYAxis: -10 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,6 +112,7 @@ export class CoreCourseCourseIndexComponent implements OnInit {
|
||||||
CoreDomUtils.scrollViewToElement(
|
CoreDomUtils.scrollViewToElement(
|
||||||
this.elementRef.nativeElement,
|
this.elementRef.nativeElement,
|
||||||
'.item.item-current',
|
'.item.item-current',
|
||||||
|
{ addYAxis: -10 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ export class CoreDomUtilsProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait an element to be in dom of another element.
|
* Wait an element to be added to the root DOM.
|
||||||
*
|
*
|
||||||
* @param element Element to wait.
|
* @param element Element to wait.
|
||||||
* @return Cancellable promise.
|
* @return Cancellable promise.
|
||||||
|
@ -130,6 +130,44 @@ export class CoreDomUtilsProvider {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait an element to be in dom of another element using a selector
|
||||||
|
*
|
||||||
|
* @param container Element to wait.
|
||||||
|
* @return Cancellable promise.
|
||||||
|
*/
|
||||||
|
async waitToBeInsideElement(container: HTMLElement, selector: string): Promise<CoreCancellablePromise<HTMLElement>> {
|
||||||
|
await CoreDomUtils.waitToBeInDOM(container);
|
||||||
|
|
||||||
|
let element = container.querySelector<HTMLElement>(selector);
|
||||||
|
if (element) {
|
||||||
|
// Already in DOM.
|
||||||
|
return CoreCancellablePromise.resolve(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
let observer: MutationObserver;
|
||||||
|
|
||||||
|
return new CoreCancellablePromise<HTMLElement>(
|
||||||
|
(resolve) => {
|
||||||
|
observer = new MutationObserver(() => {
|
||||||
|
element = container.querySelector<HTMLElement>(selector);
|
||||||
|
|
||||||
|
if (!element) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
observer?.disconnect();
|
||||||
|
resolve(element);
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(container, { subtree: true, childList: true });
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
observer?.disconnect();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait an element to be in dom and visible.
|
* Wait an element to be in dom and visible.
|
||||||
*
|
*
|
||||||
|
@ -889,7 +927,7 @@ export class CoreDomUtilsProvider {
|
||||||
*
|
*
|
||||||
* @param findFunction The function used to find the element.
|
* @param findFunction The function used to find the element.
|
||||||
* @return Resolved if found, rejected if too many tries.
|
* @return Resolved if found, rejected if too many tries.
|
||||||
* @deprecated since app 4.0 Use waitToBeInDOM instead.
|
* @deprecated since app 4.0 Use waitToBeInsideElement instead.
|
||||||
*/
|
*/
|
||||||
waitElementToExist(findFunction: () => HTMLElement | null): Promise<HTMLElement> {
|
waitElementToExist(findFunction: () => HTMLElement | null): Promise<HTMLElement> {
|
||||||
const promiseInterval = CoreUtils.promiseDefer<HTMLElement>();
|
const promiseInterval = CoreUtils.promiseDefer<HTMLElement>();
|
||||||
|
@ -1320,14 +1358,12 @@ export class CoreDomUtilsProvider {
|
||||||
*
|
*
|
||||||
* @param element The element to scroll to.
|
* @param element The element to scroll to.
|
||||||
* @param selector Selector to find the element to scroll to inside the defined element.
|
* @param selector Selector to find the element to scroll to inside the defined element.
|
||||||
* @param duration Duration of the scroll animation in milliseconds.
|
* @param scrollOptions Scroll Options.
|
||||||
* @return Wether the scroll suceeded.
|
* @return Wether the scroll suceeded.
|
||||||
*/
|
*/
|
||||||
async scrollViewToElement(element: HTMLElement, selector?: string, duration = 0): Promise<boolean> {
|
async scrollViewToElement(element: HTMLElement, selector?: string, scrollOptions: CoreScrollOptions = {}): Promise<boolean> {
|
||||||
await CoreDomUtils.waitToBeInDOM(element);
|
|
||||||
|
|
||||||
if (selector) {
|
if (selector) {
|
||||||
const foundElement = element.querySelector<HTMLElement>(selector);
|
const foundElement = await CoreDomUtils.waitToBeInsideElement(element, selector);
|
||||||
if (!foundElement) {
|
if (!foundElement) {
|
||||||
// Element not found.
|
// Element not found.
|
||||||
return false;
|
return false;
|
||||||
|
@ -1336,16 +1372,28 @@ export class CoreDomUtilsProvider {
|
||||||
element = foundElement;
|
element = foundElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await CoreDomUtils.waitToBeVisible(element);
|
||||||
|
|
||||||
const content = element.closest<HTMLIonContentElement>('ion-content') ?? undefined;
|
const content = element.closest<HTMLIonContentElement>('ion-content') ?? undefined;
|
||||||
if (!content) {
|
if (!content) {
|
||||||
|
|
||||||
// Content to scroll, not found.
|
// Content to scroll, not found.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const position = CoreDomUtils.getRelativeElementPosition(element, content);
|
const position = CoreDomUtils.getRelativeElementPosition(element, content);
|
||||||
|
const scrollElement = await content.getScrollElement();
|
||||||
|
|
||||||
await content.scrollToPoint(position.x, position.y, duration);
|
scrollOptions.duration = scrollOptions.duration ?? 200;
|
||||||
|
scrollOptions.addXAxis = scrollOptions.addXAxis ?? 0;
|
||||||
|
scrollOptions.addYAxis = scrollOptions.addYAxis ?? 0;
|
||||||
|
|
||||||
|
await content.scrollToPoint(
|
||||||
|
position.x + scrollElement.scrollLeft + scrollOptions.addXAxis,
|
||||||
|
position.y + scrollElement.scrollTop + scrollOptions.addYAxis,
|
||||||
|
scrollOptions.duration,
|
||||||
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch {
|
||||||
|
@ -1373,8 +1421,8 @@ export class CoreDomUtilsProvider {
|
||||||
* @return True if the element is found, false otherwise.
|
* @return True if the element is found, false otherwise.
|
||||||
* @deprecated since app 4.0 Use scrollViewToElement instead.
|
* @deprecated since app 4.0 Use scrollViewToElement instead.
|
||||||
*/
|
*/
|
||||||
scrollToElement(content: IonContent, element: HTMLElement, scrollParentClass?: string, duration = 0): boolean {
|
scrollToElement(content: IonContent, element: HTMLElement, scrollParentClass?: string, duration?: number): boolean {
|
||||||
CoreDomUtils.scrollViewToElement(element, undefined, duration);
|
CoreDomUtils.scrollViewToElement(element, undefined, { duration });
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1395,13 +1443,13 @@ export class CoreDomUtilsProvider {
|
||||||
content: unknown | null,
|
content: unknown | null,
|
||||||
selector: string,
|
selector: string,
|
||||||
scrollParentClass?: string,
|
scrollParentClass?: string,
|
||||||
duration = 0,
|
duration?: number,
|
||||||
): boolean {
|
): boolean {
|
||||||
if (!container || !content) {
|
if (!container || !content) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreDomUtils.scrollViewToElement(container, selector, duration);
|
CoreDomUtils.scrollViewToElement(container, selector, { duration });
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -2435,3 +2483,12 @@ export type CoreCoordinates = {
|
||||||
x: number; // X axis coordinates.
|
x: number; // X axis coordinates.
|
||||||
y: number; // Y axis coordinates.
|
y: number; // Y axis coordinates.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scroll options.
|
||||||
|
*/
|
||||||
|
export type CoreScrollOptions = {
|
||||||
|
duration?: number;
|
||||||
|
addYAxis?: number;
|
||||||
|
addXAxis?: number;
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue