Commit 678202a1 authored by H. Fischer's avatar H. Fischer
Browse files

Merge branch 'add-checking-animation' into 'master'

Add animation that is shown while checking an exercise

See merge request !19
parents 513578ea 10ce59e1
Loading
Loading
Loading
Loading
+91 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ code {
    border-radius: 10px;
    box-shadow: 4px 2px 6px black;
    margin-top: 10px;
    overflow: hidden;
}

.card .title {
@@ -67,6 +68,96 @@ code {

.card .content {
    padding: 10px;
    position: relative;
    overflow: hidden;
}

.card .content .loader {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    display: none;
    justify-content: center;
    align-items: center;
    opacity: 0;
    flex-direction: column;
    color: #ffd533;
}

.card .content .loader .loader-bg {
    background-color: #334859;
    filter: blur(7px);
    opacity: .4;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
}

.card .content .loader .loader-desc {
    z-index: 10;
}

.card .content .loader .loader-animation-wrapper {
    height: 2.4rem;
    position: relative;
}

.card .content .loader .loader-animation,
.card .content .loader .loader-animation:before,
.card .content .loader .loader-animation:after {
    background-color: #ffd533;
    display: block;
    width: .5rem;
    height: .7rem;
    border-radius: 50em;
    animation: escaleY 1s infinite ease-in-out;
}

.card .content .loader .loader-animation {
    position: relative;
    animation-delay: -0.16s;
}

.card .content .loader .loader-animation:before {
    content: '';
    position: absolute;
    top: 0;
    left: -1.4rem;
    animation-delay: -0.32s;
}

.card .content .loader .loader-animation:after {
    content: '';
    position: absolute;
    top: 0;
    left: 1.4rem;
}


@keyframes escaleY {
    0%, 80%, 100% {
        box-shadow: 0 0;
        height: 1.8rem;
    }
    40% {
        box-shadow: 0 -1em;
        height: 2.4rem;
    }
}

.card.verifying .content .loader {
    display: flex;
    transition: opacity .1s ease-in-out;
    opacity: 1;
}

.card.verifying .description, .card.verifying .actions {
    transition: filter .1s ease-in-out;
    filter: blur(1px);
}

.actions button, .actions a.btn {
+16 −2
Original line number Diff line number Diff line
@@ -73,7 +73,16 @@ export class Exercise {

    /**
     * Set the handler that is called every time the exercise's completion
     * is verified (this verification might fail or be successful)
     * is in the process of being verified.
     * @param {Function} handler Function with no parameter
     */
    onVerifiying(handler) {
        this.#context._verifyingHandler = handler
    }

    /**
     * Set the handler that is called every time the exercise's completion
     * is verified (this verification either failed or was successful)
     * @param {Function} handler Function that takes the result of the verification (true/false) as parameter 
     */
    onVerified(handler) {
@@ -124,6 +133,7 @@ class ExerciseExecutionContext {
    constructor() {
        this._describeHandler = null
        this._verifyHandler = null
        this._verifyingHandler = null
        this._confirmExerciseCompletion = null
    }

@@ -201,7 +211,10 @@ class ExerciseExecutionContext {
     */
    manualConfirmation() {
        return new Promise((resolve, _) => {
            this._confirmExerciseCompletion = resolve
            this._confirmExerciseCompletion = () => {
                this._verifyingHandler()
                resolve()
            }
        })
    }

@@ -313,6 +326,7 @@ class ExerciseRetryExecutionContext extends ExerciseExecutionContext {
        super()
        this._describeHandler = oldContext._describeHandler
        this._verifyHandler = oldContext._verifyHandler
        this._verifyingHandler = oldContext._verifyingHandler
    }

    describe() {}
+25 −1
Original line number Diff line number Diff line
@@ -35,6 +35,22 @@ export function displayAsNonCurrent(cardEl) {
    }
}

/**
 * Changes the appearance of the given exercise card so it looks like it is currently being verified
 * @param {HTMLElement} cardEl The .card element
 */
export function displayAsVerifying(cardEl) {
    cardEl.classList.add("verifying")
}

/**
 * Changes the appearance of the given exercise card so it looks normal (no verification indicator)
 * @param {HTMLElement} cardEl The .card element
 */
export function displayAsNonVerifying(cardEl) {
    cardEl.classList.remove("verifying")
}

/**
 * Create a confirm and a reset button that can be appended to the actions section of
 * an exercise card.
@@ -73,7 +89,15 @@ export function createExerciseCard(exercise, onTitleClick) {
    actionsEl.append(...createExerciseCardActionButtons(
        exercise.manuallyConfirm.bind(exercise)
    ))
    cardEl.querySelector(".content").append(descriptionEl, actionsEl)
    const loaderEl = createElementWithClass("div", "loader")
    loaderEl.innerHTML = `
    <div class="loader-bg"></div>
    <div class="loader-animation-wrapper">
        <span class="loader-animation"></span>
    </div>
    <span class="loader-desc">Deine Lösung wird überprüft...</span>
    `
    cardEl.querySelector(".content").append(descriptionEl, actionsEl, loaderEl)

    // When the title bar of an exercise is clicked, skip to that exercise
    const titleEl = cardEl.querySelector(".title")
+3 −1
Original line number Diff line number Diff line
import { State } from "./state.mjs"
import * as tests from "./exercises.mjs"
import { createExerciseCard, displayAsSolved, displayAsNonCurrent, displayAsCurrent } from "./exercises.cards.mjs"
import { createExerciseCard, displayAsSolved, displayAsNonCurrent, displayAsCurrent, displayAsVerifying, displayAsNonVerifying } from "./exercises.cards.mjs"
import { Exercise } from "./exercises.api.mjs"
import { enableAutoFocus } from "./jslinux.api.mjs"

@@ -44,8 +44,10 @@ function startExercise(exercise) {

    exercise.markAsCurrent(currentState)
    exercise.onDescribed((/** @type {string} */ description) => cardEl.querySelector(".description").textContent = description)
    exercise.onVerifiying(()=>displayAsVerifying(cardEl))
    exercise.onVerified(
        (/** @type {boolean} */ success) => {
            displayAsNonVerifying(cardEl)
            if (success) {
                exercise.markAsSolved(currentState)
                displayAsSolved(cardEl)