MOBILE-4470 quiz: Fix opacity and clickable elements on reviews
parent
e775a066ae
commit
5c099471f3
|
@ -15,7 +15,7 @@
|
|||
[contextInstanceId]="contextInstanceId" [courseId]="courseId" (afterRender)="textRendered()" />
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<div class="fake-ion-item ion-text-wrap" [hidden]="!question.loaded">
|
||||
<div class="fake-ion-item ion-text-wrap" [class.readonly]="question.readOnly" [hidden]="!question.loaded">
|
||||
<core-format-text *ngIf="question.ddArea" [adaptImg]="false" [component]="component" [componentId]="componentId"
|
||||
[text]="question.ddArea" [filter]="false" (afterRender)="ddAreaRendered()" />
|
||||
</div>
|
||||
|
|
|
@ -4,12 +4,20 @@
|
|||
:host {
|
||||
--ddimageortext-border-drop: var(--medium);
|
||||
--ddimageortext-draghome-background: var(--core-dd-question-color-2);
|
||||
--cursor: pointer;
|
||||
|
||||
.readonly,
|
||||
core-format-text ::ng-deep .readonly {
|
||||
--cursor: auto;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.addon-qtype-ddimageortext-container {
|
||||
min-height: 80px; // To display the loading.
|
||||
}
|
||||
|
||||
|
||||
core-format-text ::ng-deep {
|
||||
|
||||
div.ddarea {
|
||||
|
@ -39,7 +47,7 @@ core-format-text ::ng-deep {
|
|||
|
||||
div.draghome {
|
||||
border: 1px solid var(--core-dd-question-border);
|
||||
cursor: pointer;
|
||||
cursor: var(--cursor);
|
||||
background-color: var(--ddimageortext-draghome-background);
|
||||
display: inline-block;
|
||||
height: auto;
|
||||
|
@ -78,23 +86,17 @@ core-format-text ::ng-deep {
|
|||
|
||||
.drag {
|
||||
border: 1px solid var(--core-dd-question-border);
|
||||
cursor: pointer;
|
||||
cursor: var(--cursor);
|
||||
z-index: 2;
|
||||
}
|
||||
.drag.placed {
|
||||
border: 1px solid var(--ddimageortext-border-drop);
|
||||
}
|
||||
.dragitems.readonly .drag {
|
||||
cursor: auto;
|
||||
}
|
||||
.dragitems>div {
|
||||
.dragitems > div {
|
||||
clear: both;
|
||||
}
|
||||
.dragitems {
|
||||
cursor: pointer;
|
||||
}
|
||||
.dragitems.readonly {
|
||||
cursor: auto;
|
||||
cursor: var(--cursor);
|
||||
}
|
||||
.drag img {
|
||||
display: block;
|
||||
|
@ -106,10 +108,7 @@ core-format-text ::ng-deep {
|
|||
border: 1px solid var(--ddimageortext-border-drop);
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
.readonly .dropzone {
|
||||
cursor: auto;
|
||||
cursor: var(--cursor);
|
||||
}
|
||||
|
||||
div.dragitems div.draghome, div.dragitems div.drag {
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
// Style ddmarker content a bit. Almost all these styles are copied from Moodle.
|
||||
:host {
|
||||
--cursor: pointer;
|
||||
|
||||
.readonly,
|
||||
core-format-text ::ng-deep .readonly {
|
||||
--cursor: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.addon-qtype-ddmarker-container {
|
||||
min-height: 80px; // To display the loading.
|
||||
}
|
||||
|
@ -33,18 +42,11 @@ core-format-text ::ng-deep {
|
|||
|
||||
.dragitems, // Previous to 3.9.
|
||||
.draghomes {
|
||||
&.readonly {
|
||||
.dragitem,
|
||||
.marker {
|
||||
cursor: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.dragitem, // Previous to 3.9.
|
||||
.draghome,
|
||||
.marker {
|
||||
vertical-align: top;
|
||||
cursor: pointer;
|
||||
cursor: var(--cursor);
|
||||
position: relative;
|
||||
margin: 10px;
|
||||
display: inline-block;
|
||||
|
@ -70,7 +72,7 @@ core-format-text ::ng-deep {
|
|||
.droparea {
|
||||
.dragitem,
|
||||
.marker {
|
||||
cursor: pointer;
|
||||
cursor: var(--cursor);
|
||||
position: absolute;
|
||||
vertical-align: top;
|
||||
z-index: 2;
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
@use "theme/globals" as *;
|
||||
|
||||
// Style ddwtos content a bit. Almost all these styles are copied from Moodle.
|
||||
|
||||
:host {
|
||||
--cursor: pointer;
|
||||
|
||||
.readonly,
|
||||
core-format-text ::ng-deep .readonly {
|
||||
--cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
.addon-qtype-ddwtos-container {
|
||||
min-height: 80px; // To display the loading.
|
||||
position: relative;
|
||||
|
@ -27,7 +37,7 @@ core-format-text ::ng-deep, .drags ::ng-deep {
|
|||
border: 1px solid var(--core-dd-question-border);
|
||||
margin-bottom: 2px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
cursor: var(--cursor);
|
||||
}
|
||||
.draghome, .drag {
|
||||
display: inline-block;
|
||||
|
@ -48,7 +58,7 @@ core-format-text ::ng-deep, .drags ::ng-deep {
|
|||
z-index: 2;
|
||||
border-radius: 5px;
|
||||
line-height: 25px;
|
||||
cursor: pointer;
|
||||
cursor: var(--cursor);
|
||||
}
|
||||
.drag.selected,
|
||||
.drop.selected {
|
||||
|
@ -60,17 +70,10 @@ core-format-text ::ng-deep, .drags ::ng-deep {
|
|||
&.notreadonly .draghome,
|
||||
&.notreadonly .drop,
|
||||
&.notreadonly .answercontainer {
|
||||
cursor: pointer;
|
||||
cursor: var(--cursor);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
&.readonly .drag,
|
||||
&.readonly .draghome,
|
||||
&.readonly .drop,
|
||||
&.readonly .answercontainer {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
span.incorrect {
|
||||
background-color: var(--core-question-incorrect-color-bg);
|
||||
}
|
||||
|
|
|
@ -16,25 +16,27 @@
|
|||
<!-- Checkbox for multiple choice. -->
|
||||
<ng-container *ngIf="question.multi">
|
||||
<ion-item class="ion-text-wrap answer" *ngFor="let option of question.options">
|
||||
<ion-checkbox [attr.name]="option.name" [(ngModel)]="option.checked" [disabled]="option.disabled"
|
||||
[color]='(option.isCorrect === 1 ? "success": "") + (option.isCorrect === 0 ? "danger": "")'>
|
||||
<div>
|
||||
<div [class]="option.class">
|
||||
<core-format-text [component]="component" [componentId]="componentId" [text]="option.text"
|
||||
[contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId" />
|
||||
</div>
|
||||
<div *ngIf="option.feedback" class="specificfeedback">
|
||||
<core-format-text [component]="component" [componentId]="componentId" [text]="option.feedback"
|
||||
[contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId" />
|
||||
<div class="flex-column">
|
||||
<ion-checkbox [attr.name]="option.name" [(ngModel)]="option.checked" [disabled]="option.disabled"
|
||||
[color]='(option.isCorrect === 1 ? "success": "") + (option.isCorrect === 0 ? "danger": "")'>
|
||||
<div class="flex-grow ion-text-wrap">
|
||||
<div [class]="option.class">
|
||||
<core-format-text [component]="component" [componentId]="componentId" [text]="option.text"
|
||||
[contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId" />
|
||||
</div>
|
||||
</div>
|
||||
<ion-icon *ngIf="option.isCorrect === 1" class="core-correct-icon" name="fas-check" color="success"
|
||||
[attr.aria-label]="'core.question.correct' | translate" />
|
||||
<ion-icon *ngIf="option.isCorrect === 0" class="core-correct-icon" name="fas-xmark" color="danger"
|
||||
[attr.aria-label]="'core.question.incorrect' | translate" />
|
||||
</ion-checkbox>
|
||||
<div *ngIf="option.feedback" class="specificfeedback">
|
||||
<core-format-text [component]="component" [componentId]="componentId" [text]="option.feedback"
|
||||
[contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId" />
|
||||
</div>
|
||||
<ion-icon *ngIf="option.isCorrect === 1" class="core-correct-icon" name="fas-check" color="success"
|
||||
[attr.aria-label]="'core.question.correct' | translate" />
|
||||
<ion-icon *ngIf="option.isCorrect === 0" class="core-correct-icon" name="fas-xmark" color="danger"
|
||||
[attr.aria-label]="'core.question.incorrect' | translate" />
|
||||
</ion-checkbox>
|
||||
|
||||
</div>
|
||||
<!-- ion-checkbox doesn't use an input. Create a hidden input to hold the value. -->
|
||||
<!-- @TODO Check if this is still needed -->
|
||||
<input type="hidden" [ngModel]="option.checked" [attr.name]="option.name">
|
||||
</ion-item>
|
||||
</ng-container>
|
||||
|
@ -42,23 +44,26 @@
|
|||
<!-- Radio buttons for single choice. -->
|
||||
<ion-radio-group *ngIf="!question.multi" [(ngModel)]="question.singleChoiceModel" [name]="question.optionsName">
|
||||
<ion-item class="ion-text-wrap answer" *ngFor="let option of question.options">
|
||||
<ion-radio [value]="option.value" [disabled]="option.disabled"
|
||||
[color]='(option.isCorrect === 1 ? "success": "") + (option.isCorrect === 0 ? "danger": "")'>
|
||||
<div>
|
||||
<div [class]="option.class">
|
||||
<core-format-text [component]="component" [componentId]="componentId" [text]="option.text"
|
||||
[contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId" />
|
||||
</div>
|
||||
<div *ngIf="option.feedback" class="specificfeedback">
|
||||
<core-format-text [component]="component" [componentId]="componentId" [text]="option.feedback"
|
||||
[contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId" />
|
||||
<div class="flex-column">
|
||||
<ion-radio [value]="option.value" [disabled]="option.disabled"
|
||||
[color]='(option.isCorrect === 1 ? "success": "") + (option.isCorrect === 0 ? "danger": "")'>
|
||||
<div class="flex-grow ion-text-wrap">
|
||||
<div [class]="option.class">
|
||||
<core-format-text [component]="component" [componentId]="componentId" [text]="option.text"
|
||||
[contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId" />
|
||||
</div>
|
||||
</div>
|
||||
<ion-icon *ngIf="option.isCorrect === 1" class="core-correct-icon" name="fas-check" color="success"
|
||||
[attr.aria-label]="'core.question.correct' | translate" />
|
||||
<ion-icon *ngIf="option.isCorrect === 0" class="core-correct-icon" name="fas-xmark" color="danger"
|
||||
[attr.aria-label]="'core.question.incorrect' | translate" />
|
||||
</ion-radio>
|
||||
|
||||
<div *ngIf="option.feedback" class="specificfeedback">
|
||||
<core-format-text [component]="component" [componentId]="componentId" [text]="option.feedback"
|
||||
[contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId" />
|
||||
</div>
|
||||
<ion-icon *ngIf="option.isCorrect === 1" class="core-correct-icon" name="fas-check" color="success"
|
||||
[attr.aria-label]="'core.question.correct' | translate" />
|
||||
<ion-icon *ngIf="option.isCorrect === 0" class="core-correct-icon" name="fas-xmark" color="danger"
|
||||
[attr.aria-label]="'core.question.incorrect' | translate" />
|
||||
</ion-radio>
|
||||
</div>
|
||||
</ion-item>
|
||||
<ion-button *ngIf="!question.disabled" class="ion-text-wrap ion-margin-top" expand="block" fill="outline"
|
||||
[disabled]="!question.singleChoiceModel" (click)="clear()" type="button">
|
||||
|
@ -66,6 +71,7 @@
|
|||
</ion-button>
|
||||
|
||||
<!-- ion-radio doesn't use an input. Create a hidden input to hold the selected value. -->
|
||||
<!-- @TODO Check if this is still needed -->
|
||||
<input type="hidden" [ngModel]="question.singleChoiceModel" [attr.name]="question.optionsName">
|
||||
</ion-radio-group>
|
||||
</ion-list>
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
@use "theme/globals" as *;
|
||||
|
||||
:host ::ng-deep {
|
||||
.specificfeedback {
|
||||
background-color: var(--core-question-feedback-color-bg);
|
||||
color: var(--core-question-feedback-color);
|
||||
display: inline;
|
||||
padding: 0 .7em;
|
||||
font-size: var(--text-size);
|
||||
|
||||
@include pointer-events-on-buttons();
|
||||
}
|
||||
|
||||
.d-flex {
|
||||
|
|
|
@ -31,12 +31,10 @@
|
|||
--contents-display: block;
|
||||
|
||||
@include core-transition(all, 200ms);
|
||||
pointer-events: none;
|
||||
display: var(--contents-display);
|
||||
|
||||
&.core-loading-loaded {
|
||||
position: static;
|
||||
pointer-events: auto;
|
||||
--contents-display: contents;
|
||||
--internal-loading-inline-min-height: 0px;
|
||||
|
||||
|
|
|
@ -106,10 +106,4 @@
|
|||
.fa.icon.questioncorrectnessicon {
|
||||
font-size: var(--mdl-typography-icon-fontSize-md);
|
||||
}
|
||||
|
||||
.item.item-interactive.item-interactive-disabled ::ng-deep {
|
||||
ion-label, ion-select, ion-checkbox {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,12 +16,20 @@ input[type=checkbox] {
|
|||
}
|
||||
|
||||
ion-checkbox {
|
||||
&.md.checkbox-disabled::part(label),
|
||||
&.ios.checkbox-disabled {
|
||||
opacity: var(--mdl-input-disabled-opacity);
|
||||
&.checkbox-disabled {
|
||||
@include pointer-events-on-buttons();
|
||||
|
||||
&.md::part(label),
|
||||
&.ios {
|
||||
opacity: var(--mdl-input-disabled-opacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ios input[type=checkbox] {
|
||||
--outer-border-width: 1px;
|
||||
}
|
||||
|
||||
input[type=checkbox][disabled] {
|
||||
opacity: var(--mdl-input-disabled-opacity);
|
||||
}
|
||||
|
|
|
@ -3,3 +3,8 @@ ion-input {
|
|||
opacity: var(--mdl-input-disabled-opacity);
|
||||
}
|
||||
}
|
||||
|
||||
input[disabled],
|
||||
input[readonly] {
|
||||
opacity: var(--mdl-input-disabled-opacity);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,10 @@ ion-item.item {
|
|||
&.item-has-interactive-control:focus-within {
|
||||
@include core-focus-outline();
|
||||
}
|
||||
|
||||
&.item-has-interactive-control.item-interactive-disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Fake item.
|
||||
|
@ -246,6 +250,22 @@ ion-item.item.item-file {
|
|||
[slot=end] {
|
||||
@include margin-horizontal(var(--mdl-spacing-4), null);
|
||||
}
|
||||
|
||||
// Disabled items.
|
||||
&.item-disabled,
|
||||
&.item-interactive-disabled:not(.item-multiple-inputs) ion-label {
|
||||
opacity: var(--mdl-item-disabled-opacity) !important;
|
||||
}
|
||||
|
||||
// No highlight on RTE.
|
||||
&.item-rte {
|
||||
--full-highlight-height: 0px !important;
|
||||
}
|
||||
|
||||
&.item-multiple-inputs.only-links a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.item-dimmed {
|
||||
|
@ -255,56 +275,3 @@ ion-item.item.item-file {
|
|||
--background: var(--light);
|
||||
}
|
||||
}
|
||||
|
||||
// No highlight on RTE.
|
||||
ion-item.item-rte {
|
||||
--full-highlight-height: 0px !important;
|
||||
}
|
||||
|
||||
// Make links clickable when inside radio or checkbox items. Style part.
|
||||
@media (hover: hover) {
|
||||
ion-item.item-multiple-inputs:not(.item-rte):hover::part(native) {
|
||||
color: var(--color-hover);
|
||||
|
||||
&::after {
|
||||
background: var(--background-hover);
|
||||
opacity: var(--background-hover-opacity);
|
||||
}
|
||||
}
|
||||
|
||||
ion-item.ion-color.item-multiple-inputs:hover::part(native) {
|
||||
color: #{current-color(contrast)};
|
||||
|
||||
&::after {
|
||||
background: #{current-color(contrast)};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// It fixes the click on links where ion-ripple-effect is present.
|
||||
// Make links clickable when inside radio or checkbox items. Pointer and cursor part.
|
||||
ion-item.item-multiple-inputs:not(.only-links):not(.item-rte),
|
||||
ion-item.ion-activatable:not(.only-links) {
|
||||
cursor: pointer;
|
||||
ion-label {
|
||||
z-index: 3;
|
||||
pointer-events: none;
|
||||
|
||||
ion-anchor, a,
|
||||
ion-button, button,
|
||||
ion-item.ion-focusable,
|
||||
audio, video, select, input, iframe {
|
||||
pointer-events: visible;
|
||||
}
|
||||
}
|
||||
|
||||
ion-checkbox, ion-datetime, ion-radio, ion-select{
|
||||
position: static;
|
||||
}
|
||||
}
|
||||
|
||||
ion-item.item-multiple-inputs.only-links {
|
||||
a {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,8 +57,16 @@ input[type=radio],
|
|||
}
|
||||
|
||||
ion-radio {
|
||||
&.md.radio-disabled::part(label),
|
||||
&.ios.radio-disabled {
|
||||
opacity: var(--mdl-input-disabled-opacity);
|
||||
&.radio-disabled {
|
||||
@include pointer-events-on-buttons();
|
||||
|
||||
&.md::part(label),
|
||||
&.ios {
|
||||
opacity: var(--mdl-input-disabled-opacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input[type=radio][disabled] {
|
||||
opacity: var(--mdl-input-disabled-opacity);
|
||||
}
|
||||
|
|
|
@ -72,3 +72,7 @@ ion-select-popover {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
select[disabled] {
|
||||
opacity: var(--mdl-input-disabled-opacity);
|
||||
}
|
||||
|
|
|
@ -171,6 +171,20 @@
|
|||
}
|
||||
}
|
||||
|
||||
@mixin pointer-events-on-buttons() {
|
||||
a,
|
||||
ion-button,
|
||||
button,
|
||||
audio,
|
||||
video,
|
||||
select,
|
||||
input,
|
||||
iframe,
|
||||
[role="button"] {
|
||||
pointer-events: visible;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as item-push-svg-url but admits flip-rtl
|
||||
*/
|
||||
|
|
|
@ -63,6 +63,17 @@ html[dir=rtl] {
|
|||
flex-direction: row;
|
||||
}
|
||||
|
||||
|
||||
.flex-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.flex-grow {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.margin-bottom-sm { margin-bottom: 8px; }
|
||||
.margin-bottom-md { margin-bottom: 12px; }
|
||||
|
||||
|
@ -572,12 +583,6 @@ audio.core-media-adapt-width {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
// Disabled items.
|
||||
ion-item.item-disabled,
|
||||
ion-item.item-interactive-disabled:not(.item-multiple-inputs) ion-label {
|
||||
opacity: var(--mdl-item-disabled-opacity) !important;
|
||||
}
|
||||
|
||||
ion-item-divider.item,
|
||||
ion-item.item,
|
||||
td {
|
||||
|
|
Loading…
Reference in New Issue