MOBILE-2577 quiz: Fix position of drags when question contains images
parent
ab1c124713
commit
c14d7ad04a
|
@ -7,7 +7,7 @@
|
|||
<ion-icon name="information-circle"></ion-icon>
|
||||
{{ 'core.question.howtodraganddrop' | translate }}
|
||||
</p>
|
||||
<p><core-format-text [component]="component" [componentId]="componentId" [text]="question.text"></core-format-text></p>
|
||||
<p><core-format-text [component]="component" [componentId]="componentId" [text]="question.text" #questiontext></core-format-text></p>
|
||||
<core-format-text *ngIf="question.ddArea" [adaptImg]="false" [component]="component" [componentId]="componentId" [text]="question.ddArea" (afterRender)="questionRendered()"></core-format-text>
|
||||
</ion-item>
|
||||
</section>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, OnInit, OnDestroy, Injector, ElementRef } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy, Injector, ElementRef, ViewChild } from '@angular/core';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
import { CoreQuestionBaseComponent } from '@core/question/classes/base-question-component';
|
||||
import { AddonQtypeDdMarkerQuestion } from '../classes/ddmarker';
|
||||
|
@ -25,6 +25,7 @@ import { AddonQtypeDdMarkerQuestion } from '../classes/ddmarker';
|
|||
templateUrl: 'addon-qtype-ddmarker.html'
|
||||
})
|
||||
export class AddonQtypeDdMarkerComponent extends CoreQuestionBaseComponent implements OnInit, OnDestroy {
|
||||
@ViewChild('questiontext') questionTextEl: ElementRef;
|
||||
|
||||
protected element: HTMLElement;
|
||||
protected questionInstance: AddonQtypeDdMarkerQuestion;
|
||||
|
@ -87,9 +88,11 @@ export class AddonQtypeDdMarkerComponent extends CoreQuestionBaseComponent imple
|
|||
*/
|
||||
questionRendered(): void {
|
||||
if (!this.destroyed) {
|
||||
// Create the instance.
|
||||
this.questionInstance = new AddonQtypeDdMarkerQuestion(this.loggerProvider, this.domUtils, this.textUtils, this.element,
|
||||
this.question, this.question.readOnly, this.dropZones);
|
||||
this.domUtils.waitForImages(this.questionTextEl.nativeElement).then(() => {
|
||||
// Create the instance.
|
||||
this.questionInstance = new AddonQtypeDdMarkerQuestion(this.loggerProvider, this.domUtils, this.textUtils,
|
||||
this.element, this.question, this.question.readOnly, this.dropZones);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
<section ion-list *ngIf="question.text || question.text === ''">
|
||||
<ion-item text-wrap class="addon-qtype-ddwtos-container">
|
||||
<!-- Content is outside the core-loading to let the script calculate drag items position -->
|
||||
<core-loading [hideUntil]="question.loaded"></core-loading>
|
||||
|
||||
<ion-item text-wrap class="addon-qtype-ddwtos-container" [ngClass]="{invisible: !question.loaded}">
|
||||
<p *ngIf="!question.readOnly" class="core-info-card" icon-start>
|
||||
<ion-icon name="information-circle"></ion-icon>
|
||||
{{ 'core.question.howtodraganddrop' | translate }}
|
||||
</p>
|
||||
<p><core-format-text [component]="component" [componentId]="componentId" [text]="question.text"></core-format-text></p>
|
||||
<p><core-format-text [component]="component" [componentId]="componentId" [text]="question.text" #questiontext></core-format-text></p>
|
||||
<core-format-text *ngIf="question.answers" [component]="component" [componentId]="componentId" [text]="question.answers" (afterRender)="questionRendered()"></core-format-text>
|
||||
<div class="drags"></div>
|
||||
</ion-item>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, OnInit, OnDestroy, Injector, ElementRef } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy, Injector, ElementRef, ViewChild } from '@angular/core';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
import { CoreQuestionBaseComponent } from '@core/question/classes/base-question-component';
|
||||
import { AddonQtypeDdwtosQuestion } from '../classes/ddwtos';
|
||||
|
@ -25,6 +25,7 @@ import { AddonQtypeDdwtosQuestion } from '../classes/ddwtos';
|
|||
templateUrl: 'addon-qtype-ddwtos.html'
|
||||
})
|
||||
export class AddonQtypeDdwtosComponent extends CoreQuestionBaseComponent implements OnInit, OnDestroy {
|
||||
@ViewChild('questiontext') questionTextEl: ElementRef;
|
||||
|
||||
protected element: HTMLElement;
|
||||
protected questionInstance: AddonQtypeDdwtosQuestion;
|
||||
|
@ -80,6 +81,8 @@ export class AddonQtypeDdwtosComponent extends CoreQuestionBaseComponent impleme
|
|||
this.question.text += inputEl.outerHTML;
|
||||
this.inputIds.push(inputEl.getAttribute('id'));
|
||||
});
|
||||
|
||||
this.question.loaded = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,11 +90,15 @@ export class AddonQtypeDdwtosComponent extends CoreQuestionBaseComponent impleme
|
|||
*/
|
||||
questionRendered(): void {
|
||||
if (!this.destroyed) {
|
||||
// Create the instance.
|
||||
this.questionInstance = new AddonQtypeDdwtosQuestion(this.loggerProvider, this.domUtils, this.element, this.question,
|
||||
this.question.readOnly, this.inputIds);
|
||||
this.domUtils.waitForImages(this.questionTextEl.nativeElement).then(() => {
|
||||
// Create the instance.
|
||||
this.questionInstance = new AddonQtypeDdwtosQuestion(this.loggerProvider, this.domUtils, this.element,
|
||||
this.question, this.question.readOnly, this.inputIds);
|
||||
|
||||
this.questionHelper.treatCorrectnessIconsClicks(this.element, this.component, this.componentId);
|
||||
this.questionHelper.treatCorrectnessIconsClicks(this.element, this.component, this.componentId);
|
||||
|
||||
this.question.loaded = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import { NgModule } from '@angular/core';
|
|||
import { IonicModule } from 'ionic-angular';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CoreQuestionDelegate } from '@core/question/providers/delegate';
|
||||
import { CoreComponentsModule } from '@components/components.module';
|
||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||
import { AddonQtypeDdwtosHandler } from './providers/handler';
|
||||
import { AddonQtypeDdwtosComponent } from './component/ddwtos';
|
||||
|
@ -27,6 +28,7 @@ import { AddonQtypeDdwtosComponent } from './component/ddwtos';
|
|||
imports: [
|
||||
IonicModule,
|
||||
TranslateModule.forChild(),
|
||||
CoreComponentsModule,
|
||||
CoreDirectivesModule
|
||||
],
|
||||
providers: [
|
||||
|
|
|
@ -296,7 +296,7 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
this.calculateHeight();
|
||||
|
||||
// Wait for images to load and calculate the height again if needed.
|
||||
this.waitForImages().then((hasImgToLoad) => {
|
||||
this.domUtils.waitForImages(this.element).then((hasImgToLoad) => {
|
||||
if (hasImgToLoad) {
|
||||
this.calculateHeight();
|
||||
}
|
||||
|
@ -628,39 +628,6 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
this.iframeUtils.treatFrame(iframe);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for images to load.
|
||||
*
|
||||
* @return {Promise<boolean>} Promise resolved with a boolean: whether there was any image to load.
|
||||
*/
|
||||
protected waitForImages(): Promise<boolean> {
|
||||
const imgs = Array.from(this.element.querySelectorAll('img')),
|
||||
promises = [];
|
||||
let hasImgToLoad = false;
|
||||
|
||||
imgs.forEach((img) => {
|
||||
if (img && !img.complete) {
|
||||
hasImgToLoad = true;
|
||||
|
||||
// Wait for image to load or fail.
|
||||
promises.push(new Promise((resolve, reject): void => {
|
||||
const imgLoaded = (): void => {
|
||||
resolve();
|
||||
img.removeEventListener('loaded', imgLoaded);
|
||||
img.removeEventListener('error', imgLoaded);
|
||||
};
|
||||
|
||||
img.addEventListener('load', imgLoaded);
|
||||
img.addEventListener('error', imgLoaded);
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.all(promises).then(() => {
|
||||
return hasImgToLoad;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to extract YouTube Id to translate to embedded video.
|
||||
* Based on http://stackoverflow.com/questions/3452546/javascript-regex-how-to-get-youtube-video-id-from-url
|
||||
|
|
|
@ -1258,6 +1258,40 @@ export class CoreDomUtilsProvider {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for images to load.
|
||||
*
|
||||
* @param {HTMLElement} element The element to search in.
|
||||
* @return {Promise<boolean>} Promise resolved with a boolean: whether there was any image to load.
|
||||
*/
|
||||
waitForImages(element: HTMLElement): Promise<boolean> {
|
||||
const imgs = Array.from(element.querySelectorAll('img')),
|
||||
promises = [];
|
||||
let hasImgToLoad = false;
|
||||
|
||||
imgs.forEach((img) => {
|
||||
if (img && !img.complete) {
|
||||
hasImgToLoad = true;
|
||||
|
||||
// Wait for image to load or fail.
|
||||
promises.push(new Promise((resolve, reject): void => {
|
||||
const imgLoaded = (): void => {
|
||||
resolve();
|
||||
img.removeEventListener('load', imgLoaded);
|
||||
img.removeEventListener('error', imgLoaded);
|
||||
};
|
||||
|
||||
img.addEventListener('load', imgLoaded);
|
||||
img.addEventListener('error', imgLoaded);
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.all(promises).then(() => {
|
||||
return hasImgToLoad;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap an HTMLElement with another element.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue