forked from EVOgeek/Vmeda.Online
		
	MOBILE-3814 ddwtos: Use dom Promises to know if element is ready
This commit is contained in:
		
							parent
							
								
									505891fa11
								
							
						
					
					
						commit
						dbc91004e4
					
				| @ -12,9 +12,11 @@ | |||||||
| // 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 { CoreFormatTextDirective } from '@directives/format-text'; | ||||||
| import { CoreDomUtils } from '@services/utils/dom'; | import { CoreDomUtils } from '@services/utils/dom'; | ||||||
| import { CoreTextUtils } from '@services/utils/text'; | import { CoreTextUtils } from '@services/utils/text'; | ||||||
| import { CoreUtils } from '@services/utils/utils'; | import { CoreUtils } from '@services/utils/utils'; | ||||||
|  | import { CoreComponentsRegistry } from '@singletons/components-registry'; | ||||||
| import { CoreEventObserver } from '@singletons/events'; | import { CoreEventObserver } from '@singletons/events'; | ||||||
| import { CoreLogger } from '@singletons/logger'; | import { CoreLogger } from '@singletons/logger'; | ||||||
| import { AddonModQuizDdwtosQuestionData } from '../component/ddwtos'; | import { AddonModQuizDdwtosQuestionData } from '../component/ddwtos'; | ||||||
| @ -26,7 +28,7 @@ export class AddonQtypeDdwtosQuestion { | |||||||
| 
 | 
 | ||||||
|     protected logger: CoreLogger; |     protected logger: CoreLogger; | ||||||
|     protected nextDragItemNo = 1; |     protected nextDragItemNo = 1; | ||||||
|     protected selectors!: AddonQtypeDdwtosQuestionCSSSelectors; // Result of cssSelectors.
 |     protected selectors = new AddonQtypeDdwtosQuestionCSSSelectors(); // Result of cssSelectors.
 | ||||||
|     protected placed: {[no: number]: number} = {}; // Map that relates drag elements numbers with drop zones numbers.
 |     protected placed: {[no: number]: number} = {}; // Map that relates drag elements numbers with drop zones numbers.
 | ||||||
|     protected selected?: HTMLElement; // Selected element (being "dragged").
 |     protected selected?: HTMLElement; // Selected element (being "dragged").
 | ||||||
|     protected resizeListener?: CoreEventObserver; |     protected resizeListener?: CoreEventObserver; | ||||||
| @ -80,8 +82,8 @@ export class AddonQtypeDdwtosQuestion { | |||||||
|      * Invisible 'drag homes' are output in the question. These have the same properties as the drag items but are invisible. |      * Invisible 'drag homes' are output in the question. These have the same properties as the drag items but are invisible. | ||||||
|      * We clone these invisible elements to make the actual drag items. |      * We clone these invisible elements to make the actual drag items. | ||||||
|      */ |      */ | ||||||
|     cloneDragItems(): void { |     async cloneDragItems(): Promise<void> { | ||||||
|         const dragHomes = <HTMLElement[]> Array.from(this.container.querySelectorAll(this.selectors.dragHomes())); |         const dragHomes = Array.from(this.container.querySelectorAll<HTMLElement>(this.selectors.dragHomes())); | ||||||
|         for (let x = 0; x < dragHomes.length; x++) { |         for (let x = 0; x < dragHomes.length; x++) { | ||||||
|             this.cloneDragItemsForOneChoice(dragHomes[x]); |             this.cloneDragItemsForOneChoice(dragHomes[x]); | ||||||
|         } |         } | ||||||
| @ -110,7 +112,7 @@ export class AddonQtypeDdwtosQuestion { | |||||||
|      */ |      */ | ||||||
|     deselectDrags(): void { |     deselectDrags(): void { | ||||||
|         // Remove the selected class from all drags.
 |         // Remove the selected class from all drags.
 | ||||||
|         const drags = <HTMLElement[]> Array.from(this.container.querySelectorAll(this.selectors.drags())); |         const drags = Array.from(this.container.querySelectorAll<HTMLElement>(this.selectors.drags())); | ||||||
|         drags.forEach((drag) => { |         drags.forEach((drag) => { | ||||||
|             drag.classList.remove('selected'); |             drag.classList.remove('selected'); | ||||||
|         }); |         }); | ||||||
| @ -192,19 +194,13 @@ export class AddonQtypeDdwtosQuestion { | |||||||
|      * Initialize the question. |      * Initialize the question. | ||||||
|      */ |      */ | ||||||
|     async initializer(): Promise<void> { |     async initializer(): Promise<void> { | ||||||
|         this.selectors = new AddonQtypeDdwtosQuestionCSSSelectors(); |         const container = this.container.querySelector<HTMLElement>(this.selectors.topNode()); | ||||||
| 
 |         container?.classList.add(this.readOnly ? 'readonly' : 'notreadonly'); | ||||||
|         const container = <HTMLElement> this.container.querySelector(this.selectors.topNode()); |  | ||||||
|         if (this.readOnly) { |  | ||||||
|             container.classList.add('readonly'); |  | ||||||
|         } else { |  | ||||||
|             container.classList.add('notreadonly'); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         // Wait for the elements to be ready.
 |         // Wait for the elements to be ready.
 | ||||||
|         await this.waitForReady(); |         await this.waitForReady(); | ||||||
| 
 | 
 | ||||||
|         this.setPaddingSizesAll(); |         await this.setPaddingSizesAll(); | ||||||
|         this.cloneDragItems(); |         this.cloneDragItems(); | ||||||
|         this.initialPlaceOfDragItems(); |         this.initialPlaceOfDragItems(); | ||||||
|         this.makeDropZones(); |         this.makeDropZones(); | ||||||
| @ -220,7 +216,7 @@ export class AddonQtypeDdwtosQuestion { | |||||||
|      * Initialize drag items, putting them in their initial place. |      * Initialize drag items, putting them in their initial place. | ||||||
|      */ |      */ | ||||||
|     initialPlaceOfDragItems(): void { |     initialPlaceOfDragItems(): void { | ||||||
|         const drags = <HTMLElement[]> Array.from(this.container.querySelectorAll(this.selectors.drags())); |         const drags = Array.from(this.container.querySelectorAll<HTMLElement>(this.selectors.drags())); | ||||||
| 
 | 
 | ||||||
|         // Add the class 'unplaced' to all elements.
 |         // Add the class 'unplaced' to all elements.
 | ||||||
|         drags.forEach((drag) => { |         drags.forEach((drag) => { | ||||||
| @ -292,15 +288,15 @@ export class AddonQtypeDdwtosQuestion { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Create all the drop zones.
 |         // Create all the drop zones.
 | ||||||
|         const drops = <HTMLElement[]> Array.from(this.container.querySelectorAll(this.selectors.drops())); |         const drops = Array.from(this.container.querySelectorAll<HTMLElement>(this.selectors.drops())); | ||||||
|         drops.forEach((drop) => { |         drops.forEach((drop) => { | ||||||
|             this.makeDropZone(drop); |             this.makeDropZone(drop); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         // If home answer zone is clicked, return drag home.
 |         // If home answer zone is clicked, return drag home.
 | ||||||
|         const home = <HTMLElement> this.container.querySelector(this.selectors.topNode() + ' .answercontainer'); |         const home = this.container.querySelector<HTMLElement>(this.selectors.topNode() + ' .answercontainer'); | ||||||
| 
 | 
 | ||||||
|         home.addEventListener('click', () => { |         home?.addEventListener('click', () => { | ||||||
|             const drag = this.selected; |             const drag = this.selected; | ||||||
|             if (!drag) { |             if (!drag) { | ||||||
|                 // No element selected, nothing to do.
 |                 // No element selected, nothing to do.
 | ||||||
| @ -413,36 +409,25 @@ export class AddonQtypeDdwtosQuestion { | |||||||
|      * Postition, or reposition, all the drag items. They're placed in the right drop zone or in the home zone. |      * Postition, or reposition, all the drag items. They're placed in the right drop zone or in the home zone. | ||||||
|      */ |      */ | ||||||
|     positionDragItems(): void { |     positionDragItems(): void { | ||||||
|         const drags = <HTMLElement[]> Array.from(this.container.querySelectorAll(this.selectors.drags())); |         const drags = Array.from(this.container.querySelectorAll<HTMLElement>(this.selectors.drags())); | ||||||
|         drags.forEach((drag) => { |         drags.forEach((drag) => { | ||||||
|             this.positionDragItem(drag); |             this.positionDragItem(drag); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Wait for the drag items to have an offsetParent. For some reason it takes a while. |      * Wait for the drag home items to be in DOM. | ||||||
|      * |      * | ||||||
|      * @param retries Number of times this has been retried. |      * @return Promise resolved when ready in the DOM. | ||||||
|      * @return Promise resolved when ready or if it took too long to load. |  | ||||||
|      */ |      */ | ||||||
|     protected async waitForReady(retries: number = 0): Promise<void> { |     protected async waitForReady(): Promise<void> { | ||||||
|         const drag = <HTMLElement | null> Array.from(this.container.querySelectorAll(this.selectors.drags()))[0]; |         await CoreDomUtils.waitToBeInDOM(this.container); | ||||||
|         if (drag?.offsetParent || retries >= 10) { |  | ||||||
|             // Ready or too many retries, stop.
 |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         const deferred = CoreUtils.promiseDefer<void>(); |         await CoreComponentsRegistry.waitComponentsReady(this.container, 'core-format-text', CoreFormatTextDirective); | ||||||
| 
 | 
 | ||||||
|         setTimeout(async () => { |         const drag = Array.from(this.container.querySelectorAll<HTMLElement>(this.selectors.dragHomes()))[0]; | ||||||
|             try { |  | ||||||
|                 await this.waitForReady(retries + 1); |  | ||||||
|             } finally { |  | ||||||
|                 deferred.resolve(); |  | ||||||
|             } |  | ||||||
|         }, 20); |  | ||||||
| 
 | 
 | ||||||
|         return deferred.promise; |         await CoreDomUtils.waitToBeInDOM(drag); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -452,7 +437,7 @@ export class AddonQtypeDdwtosQuestion { | |||||||
|      */ |      */ | ||||||
|     removeDragFromDrop(drag: HTMLElement): void { |     removeDragFromDrop(drag: HTMLElement): void { | ||||||
|         const placeNo = this.placed[this.getNo(drag) ?? -1]; |         const placeNo = this.placed[this.getNo(drag) ?? -1]; | ||||||
|         const drop = <HTMLElement> this.container.querySelector(this.selectors.dropForPlace(placeNo)); |         const drop = this.container.querySelector<HTMLElement>(this.selectors.dropForPlace(placeNo)); | ||||||
| 
 | 
 | ||||||
|         this.placeDragInDrop(null, drop); |         this.placeDragInDrop(null, drop); | ||||||
|     } |     } | ||||||
| @ -473,9 +458,9 @@ export class AddonQtypeDdwtosQuestion { | |||||||
|     /** |     /** | ||||||
|      * Set the padding size for all groups. |      * Set the padding size for all groups. | ||||||
|      */ |      */ | ||||||
|     setPaddingSizesAll(): void { |     async setPaddingSizesAll(): Promise<void> { | ||||||
|         for (let groupNo = 1; groupNo <= 8; groupNo++) { |         for (let groupNo = 1; groupNo <= 8; groupNo++) { | ||||||
|             this.setPaddingSizeForGroup(groupNo); |             await this.setPaddingSizeForGroup(groupNo); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -484,19 +469,25 @@ export class AddonQtypeDdwtosQuestion { | |||||||
|      * |      * | ||||||
|      * @param groupNo Group number. |      * @param groupNo Group number. | ||||||
|      */ |      */ | ||||||
|     setPaddingSizeForGroup(groupNo: number): void { |     async setPaddingSizeForGroup(groupNo: number): Promise<void> { | ||||||
|         const groupItems = <HTMLElement[]> Array.from(this.container.querySelectorAll(this.selectors.dragHomesGroup(groupNo))); |         const groupItems = Array.from(this.container.querySelectorAll<HTMLElement>(this.selectors.dragHomesGroup(groupNo))); | ||||||
| 
 | 
 | ||||||
|         if (!groupItems.length) { |         if (!groupItems.length) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         await CoreDomUtils.waitToBeInDOM(groupItems[0]); | ||||||
|  | 
 | ||||||
|         let maxWidth = 0; |         let maxWidth = 0; | ||||||
|         let maxHeight = 0; |         let maxHeight = 0; | ||||||
| 
 |  | ||||||
|         // Find max height and width.
 |         // Find max height and width.
 | ||||||
|         groupItems.forEach((item) => { |         groupItems.forEach((item) => { | ||||||
|             item.innerHTML = CoreTextUtils.decodeHTML(item.innerHTML); |             item.innerHTML = CoreTextUtils.decodeHTML(item.innerHTML); | ||||||
|  |         }); | ||||||
|  |         // Wait to render in order to calculate size.
 | ||||||
|  |         await CoreUtils.nextTick(); | ||||||
|  | 
 | ||||||
|  |         groupItems.forEach((item) => { | ||||||
|             maxWidth = Math.max(maxWidth, Math.ceil(item.offsetWidth)); |             maxWidth = Math.max(maxWidth, Math.ceil(item.offsetWidth)); | ||||||
|             maxHeight = Math.max(maxHeight, Math.ceil(item.offsetHeight)); |             maxHeight = Math.max(maxHeight, Math.ceil(item.offsetHeight)); | ||||||
|         }); |         }); | ||||||
| @ -507,7 +498,7 @@ export class AddonQtypeDdwtosQuestion { | |||||||
|             this.padToWidthHeight(item, maxWidth, maxHeight); |             this.padToWidthHeight(item, maxWidth, maxHeight); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         const dropsGroup = <HTMLElement[]> Array.from(this.container.querySelectorAll(this.selectors.dropsGroup(groupNo))); |         const dropsGroup = Array.from(this.container.querySelectorAll<HTMLElement>(this.selectors.dropsGroup(groupNo))); | ||||||
|         dropsGroup.forEach((item) => { |         dropsGroup.forEach((item) => { | ||||||
|             this.padToWidthHeight(item, maxWidth + 2, maxHeight + 2); |             this.padToWidthHeight(item, maxWidth + 2, maxHeight + 2); | ||||||
|         }); |         }); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user