var H5P = H5P || {};
/**
 * Transition contains helper function relevant for transitioning
 */
H5P.Transition = (function ($) {

  /**
   * @class
   * @namespace H5P
   */
  Transition = {};

  /**
   * @private
   */
  Transition.transitionEndEventNames = {
    'WebkitTransition': 'webkitTransitionEnd',
    'transition':       'transitionend',
    'MozTransition':    'transitionend',
    'OTransition':      'oTransitionEnd',
    'msTransition':     'MSTransitionEnd'
  };

  /**
   * @private
   */
  Transition.cache = [];

  /**
   * Get the vendor property name for an event
   *
   * @function H5P.Transition.getVendorPropertyName
   * @static
   * @private
   * @param  {string} prop Generic property name
   * @return {string}      Vendor specific property name
   */
  Transition.getVendorPropertyName = function (prop) {

    if (Transition.cache[prop] !== undefined) {
      return Transition.cache[prop];
    }

    var div = document.createElement('div');

    // Handle unprefixed versions (FF16+, for example)
    if (prop in div.style) {
      Transition.cache[prop] = prop;
    }
    else {
      var prefixes = ['Moz', 'Webkit', 'O', 'ms'];
      var prop_ = prop.charAt(0).toUpperCase() + prop.substr(1);

      if (prop in div.style) {
        Transition.cache[prop] = prop;
      }
      else {
        for (var i = 0; i < prefixes.length; ++i) {
          var vendorProp = prefixes[i] + prop_;
          if (vendorProp in div.style) {
            Transition.cache[prop] = vendorProp;
            break;
          }
        }
      }
    }

    return Transition.cache[prop];
  };

  /**
   * Get the name of the transition end event
   *
   * @static
   * @private
   * @return {string}  description
   */
  Transition.getTransitionEndEventName = function () {
    return Transition.transitionEndEventNames[Transition.getVendorPropertyName('transition')] || undefined;
  };

  /**
   * Helper function for listening on transition end events
   *
   * @function H5P.Transition.onTransitionEnd
   * @static
   * @param  {domElement} $element The element which is transitioned
   * @param  {function} callback The callback to be invoked when transition is finished
   * @param  {number} timeout  Timeout in milliseconds. Fallback if transition event is never fired
   */
  Transition.onTransitionEnd = function ($element, callback, timeout) {
    // Fallback on 1 second if transition event is not supported/triggered
    timeout = timeout || 1000;
    Transition.transitionEndEventName = Transition.transitionEndEventName || Transition.getTransitionEndEventName();
    var callbackCalled = false;

    var doCallback = function () {
      if (callbackCalled) {
        return;
      }
      $element.off(Transition.transitionEndEventName, callback);
      callbackCalled = true;
      clearTimeout(timer);
      callback();
    };

    var timer = setTimeout(function () {
      doCallback();
    }, timeout);

    $element.on(Transition.transitionEndEventName, function () {
      doCallback();
    });
  };

  /**
   * Wait for a transition - when finished, invokes next in line
   *
   * @private
   *
   * @param {Object[]}    transitions             Array of transitions
   * @param {H5P.jQuery}  transitions[].$element  Dom element transition is performed on
   * @param {number=}     transitions[].timeout   Timeout fallback if transition end never is triggered
   * @param {bool=}       transitions[].break     If true, sequence breaks after this transition
   * @param {number}      index                   The index for current transition
   */
  var runSequence = function (transitions, index) {
    if (index >= transitions.length) {
      return;
    }

    var transition = transitions[index];
    H5P.Transition.onTransitionEnd(transition.$element, function () {
      if (transition.end) {
        transition.end();
      }
      if (transition.break !== true) {
        runSequence(transitions, index+1);
      }
    }, transition.timeout || undefined);
  };

  /**
   * Run a sequence of transitions
   *
   * @function H5P.Transition.sequence
   * @static
   * @param {Object[]}    transitions             Array of transitions
   * @param {H5P.jQuery}  transitions[].$element  Dom element transition is performed on
   * @param {number=}     transitions[].timeout   Timeout fallback if transition end never is triggered
   * @param {bool=}       transitions[].break     If true, sequence breaks after this transition
   */
  Transition.sequence = function (transitions) {
    runSequence(transitions, 0);
  };

  return Transition;
})(H5P.jQuery);
;var H5P = H5P || {};

/**
 * H5P audio module
 *
 * @external {jQuery} $ H5P.jQuery
 */
H5P.Audio = (function ($) {
  /**
  * @param {Object} params Options for this library.
  * @param {Number} id Content identifier.
  * @param {Object} extras Extras.
  * @returns {undefined}
  */
  function C(params, id, extras) {
    H5P.EventDispatcher.call(this);

    this.contentId = id;
    this.params = params;
    this.extras = extras;
    this.toggleButtonEnabled = true;

    // Retrieve previous state
    if (extras && extras.previousState !== undefined) {
      this.oldTime = extras.previousState.currentTime;
    }

    this.params = $.extend({}, {
      playerMode: 'minimalistic',
      fitToWrapper: false,
      controls: true,
      autoplay: false,
      audioNotSupported: "Your browser does not support this audio",
      playAudio: "Play audio",
      pauseAudio: "Pause audio",
      propagateButtonClickEvents: true
    }, params);

    // Required if e.g. used in CoursePresentation as area to click on
    if (this.params.playerMode === 'transparent') {
      this.params.fitToWrapper = true;
    }

    this.on('resize', this.resize, this);
  }

  C.prototype = Object.create(H5P.EventDispatcher.prototype);
  C.prototype.constructor = C;

  /**
   * Adds a minimalistic audio player with only "play" and "pause" functionality.
   *
   * @param {jQuery} $container Container for the player.
   * @param {boolean} transparentMode true: the player is only visible when hovering over it; false: player's UI always visible
   */
  C.prototype.addMinimalAudioPlayer = function ($container, transparentMode) {
    var INNER_CONTAINER = 'h5p-audio-inner';
    var AUDIO_BUTTON = 'h5p-audio-minimal-button';
    var PLAY_BUTTON = 'h5p-audio-minimal-play';
    var PLAY_BUTTON_PAUSED = 'h5p-audio-minimal-play-paused';
    var PAUSE_BUTTON = 'h5p-audio-minimal-pause';

    var self = this;
    this.$container = $container;

    self.$inner = $('<div/>', {
      'class': INNER_CONTAINER + (transparentMode ? ' h5p-audio-transparent' : '')
    }).appendTo($container);

    var audioButton = $('<button/>', {
      'class': AUDIO_BUTTON + " " + PLAY_BUTTON,
      'aria-label': this.params.playAudio
    }).appendTo(self.$inner)
      .click( function (event) {
        if (!self.params.propagateButtonClickEvents){
          event.stopPropagation();
        }

        if (!self.isEnabledToggleButton()) {
          return;
        }

        // Prevent ARIA from playing over audio on click
        this.setAttribute('aria-hidden', 'true');

        if (self.audio.paused) {
          self.play();
        }
        else {
          self.pause();
        }
      })
      .on('focusout', function () {
        // Restore ARIA, required when playing longer audio and tabbing out and back in
        this.setAttribute('aria-hidden', 'false');
      });

    // Fit to wrapper
    if (this.params.fitToWrapper) {
      audioButton.css({
        'width': '100%',
        'height': '100%'
      });
    }

    //Event listeners that change the look of the player depending on events.
    self.audio.addEventListener('ended', function () {
      audioButton
        .attr('aria-hidden', false)
        .attr('aria-label', self.params.playAudio)
        .removeClass(PAUSE_BUTTON)
        .removeClass(PLAY_BUTTON_PAUSED)
        .addClass(PLAY_BUTTON);
    });

    self.audio.addEventListener('play', function () {
      audioButton
        .attr('aria-label', self.params.pauseAudio)
        .removeClass(PLAY_BUTTON)
        .removeClass(PLAY_BUTTON_PAUSED)
        .addClass(PAUSE_BUTTON);
    });

    self.audio.addEventListener('pause', function () {
      // Don't override if initial look is set
      if (!audioButton.hasClass(PLAY_BUTTON)) {
        audioButton
          .attr('aria-hidden', false)
          .attr('aria-label', self.params.playAudio)
          .removeClass(PAUSE_BUTTON)
          .addClass(PLAY_BUTTON_PAUSED);
      }
    });

    H5P.Audio.MINIMAL_BUTTON = AUDIO_BUTTON + " " + PLAY_BUTTON;
    H5P.Audio.MINIMAL_BUTTON_PAUSED = AUDIO_BUTTON + " " + PLAY_BUTTON_PAUSED;

    this.$audioButton = audioButton;
    // Scale icon to container
    self.resize();
  };

  /**
   * Resizes the audio player icon when the wrapper is resized.
   */
  C.prototype.resize = function () {
    // Find the smallest value of height and width, and use it to choose the font size.
    if (this.params.fitToWrapper && this.$container && this.$container.width()) {
      var w = this.$container.width();
      var h = this.$container.height();
      if (w < h) {
        this.$audioButton.css({'font-size': w / 2 + 'px'});
      }
      else {
        this.$audioButton.css({'font-size': h / 2 + 'px'});
      }
    }
  };

  return C;
})(H5P.jQuery);

/**
 * Wipe out the content of the wrapper and put our HTML in it.
 *
 * @param {jQuery} $wrapper Our poor container.
 */
H5P.Audio.prototype.attach = function ($wrapper) {
  const self = this;
  $wrapper.addClass('h5p-audio-wrapper');

  // Check if browser supports audio.
  var audio = document.createElement('audio');
  if (audio.canPlayType === undefined) {
    this.attachNotSupportedMessage($wrapper);
    return;
  }

  // Add supported source files.
  if (this.params.files !== undefined && this.params.files instanceof Object) {
    for (var i = 0; i < this.params.files.length; i++) {
      var file = this.params.files[i];

      if (audio.canPlayType(file.mime)) {
        var source = document.createElement('source');
        source.src = H5P.getPath(file.path, this.contentId);
        source.type = file.mime;
        audio.appendChild(source);
      }
    }
  }

  if (!audio.children.length) {
    this.attachNotSupportedMessage($wrapper);
    return;
  }

  if (this.endedCallback !== undefined) {
    audio.addEventListener('ended', this.endedCallback, false);
  }

  audio.className = 'h5p-audio';
  audio.controls = this.params.controls === undefined ? true : this.params.controls;

  // Menu removed, because it's cut off if audio is used as H5P.Question intro
  const controlsList = 'nodownload noplaybackrate';
  audio.setAttribute('controlsList', controlsList);

  audio.preload = 'auto';
  audio.style.display = 'block';

  if (this.params.fitToWrapper === undefined || this.params.fitToWrapper) {
    audio.style.width = '100%';
    if (!this.isRoot()) {
      // Only set height if this isn't a root
      audio.style.height = '100%';
    }
  }

  this.audio = audio;

  if (this.params.playerMode === 'minimalistic') {
    audio.controls = false;
    this.addMinimalAudioPlayer($wrapper, false);
  }
  else if (this.params.playerMode === 'transparent') {
    audio.controls = false;
    this.addMinimalAudioPlayer($wrapper, true);
  }
  else {
    $wrapper.html(audio);
  }

  if (audio.controls) {
    $wrapper.addClass('h5p-audio-controls');
  }

  // Set time to saved time from previous run
  if (this.oldTime) {
    if (this.$audioButton) {
      this.$audioButton.attr('class', H5P.Audio.MINIMAL_BUTTON_PAUSED);
    }
    this.seekTo(this.oldTime);
  }

  // Avoid autoplaying in authoring tool
  if (window.H5PEditor === undefined) {
    // Keep record of autopauses.
    // I.e: we don't wanna autoplay if the user has excplicitly paused.
    self.autoPaused = true;

    // Set up intersection observer
    new IntersectionObserver(function (entries) {
      const entry = entries[0];

      if (entry.intersectionRatio == 0) {
        if (!self.audio.paused) {
          // Audio element is hidden, pause it
          self.autoPaused = true;
          self.audio.pause();
        }
      }
      else if (self.params.autoplay && self.autoPaused) {
        // Audio element is visible. Autoplay if autoplay is enabled and it was
        // not explicitly paused by a user
        self.autoPaused = false;
        self.play();
      }
    }, {
      root: document.documentElement,
      threshold: [0, 1] // Get events when it is shown and hidden
    }).observe($wrapper.get(0));
  }
};

/**
 * Attaches not supported message.
 *
 * @param {jQuery} $wrapper Our dear container.
 */
H5P.Audio.prototype.attachNotSupportedMessage = function ($wrapper) {
  $wrapper.addClass('h5p-audio-not-supported');
  $wrapper.html(
    '<div class="h5p-audio-inner">' +
      '<div class="h5p-audio-not-supported-icon"><span/></div>' +
      '<span>' + this.params.audioNotSupported + '</span>' +
    '</div>'
  );

  if (this.endedCallback !== undefined) {
    this.endedCallback();
  }
}

/**
 * Stop & reset playback.
 *
 * @returns {undefined}
 */
H5P.Audio.prototype.resetTask = function () {
  this.stop();
  this.seekTo(0);
  if (this.$audioButton) {
    this.$audioButton.attr('class', H5P.Audio.MINIMAL_BUTTON);
  }
};

/**
 * Stop the audio. TODO: Rename to pause?
 *
 * @returns {undefined}
 */
H5P.Audio.prototype.stop = function () {
  if (this.audio !== undefined) {
    this.audio.pause();
  }
};

/**
 * Play
 */
H5P.Audio.prototype.play = function () {
  if (this.audio !== undefined) {
    // play() returns a Promise that can fail, e.g. while autoplaying
    this.audio.play().catch((error) => {
      console.warn(error);
    });
  }
};

/**
 * @public
 * Pauses the audio.
 */
H5P.Audio.prototype.pause = function () {
  if (this.audio !== undefined) {
    this.audio.pause();
  }
};

/**
 * @public
 * Seek to audio position.
 *
 * @param {number} seekTo Time to seek to in seconds.
 */
H5P.Audio.prototype.seekTo = function (seekTo) {
  if (this.audio !== undefined) {
    this.audio.currentTime = seekTo;
  }
};

/**
 * @public
 * Get current state for resetting it later.
 *
 * @returns {object} Current state.
 */
H5P.Audio.prototype.getCurrentState = function () {
  if (this.audio !== undefined && this.audio.currentTime > 0) {
    const currentTime = this.audio.ended ? 0 : this.audio.currentTime;
    return {
      currentTime: currentTime
    };
  }
};

/**
 * @public
 * Disable button.
 * Not using disabled attribute to block button activation, because it will
 * implicitly set tabindex = -1 and confuse ChromeVox navigation. Clicks handled
 * using "pointer-events: none" in CSS.
 */
H5P.Audio.prototype.disableToggleButton = function () {
  this.toggleButtonEnabled = false;
  if (this.$audioButton) {
    this.$audioButton.addClass(H5P.Audio.BUTTON_DISABLED);
  }
};

/**
 * @public
 * Enable button.
 */
H5P.Audio.prototype.enableToggleButton = function () {
  this.toggleButtonEnabled = true;
  if (this.$audioButton) {
    this.$audioButton.removeClass(H5P.Audio.BUTTON_DISABLED);
  }
};

/**
 * @public
 * Check if button is enabled.
 * @return {boolean} True, if button is enabled. Else false.
 */
H5P.Audio.prototype.isEnabledToggleButton = function () {
  return this.toggleButtonEnabled;
};

/** @constant {string} */
H5P.Audio.BUTTON_DISABLED = 'h5p-audio-disabled';
;var H5P = H5P || {};

/**
 * Class responsible for creating a help text dialog
 */
H5P.JoubelHelpTextDialog = (function ($) {

  var numInstances = 0;
  /**
   * Display a pop-up containing a message.
   *
   * @param {H5P.jQuery}  $container  The container which message dialog will be appended to
   * @param {string}      message     The message
   * @param {string}      closeButtonTitle The title for the close button
   * @return {H5P.jQuery}
   */
  function JoubelHelpTextDialog(header, message, closeButtonTitle) {
    H5P.EventDispatcher.call(this);

    var self = this;

    numInstances++;
    var headerId = 'joubel-help-text-header-' + numInstances;
    var helpTextId = 'joubel-help-text-body-' + numInstances;

    var $helpTextDialogBox = $('<div>', {
      'class': 'joubel-help-text-dialog-box',
      'role': 'dialog',
      'aria-labelledby': headerId,
      'aria-describedby': helpTextId
    });

    $('<div>', {
      'class': 'joubel-help-text-dialog-background'
    }).appendTo($helpTextDialogBox);

    var $helpTextDialogContainer = $('<div>', {
      'class': 'joubel-help-text-dialog-container'
    }).appendTo($helpTextDialogBox);

    $('<div>', {
      'class': 'joubel-help-text-header',
      'id': headerId,
      'role': 'header',
      'html': header
    }).appendTo($helpTextDialogContainer);

    $('<div>', {
      'class': 'joubel-help-text-body',
      'id': helpTextId,
      'html': message,
      'role': 'document',
      'tabindex': 0
    }).appendTo($helpTextDialogContainer);

    var handleClose = function () {
      $helpTextDialogBox.remove();
      self.trigger('closed');
    };

    var $closeButton = $('<div>', {
      'class': 'joubel-help-text-remove',
      'role': 'button',
      'title': closeButtonTitle,
      'tabindex': 1,
      'click': handleClose,
      'keydown': function (event) {
        // 32 - space, 13 - enter
        if ([32, 13].indexOf(event.which) !== -1) {
          event.preventDefault();
          handleClose();
        }
      }
    }).appendTo($helpTextDialogContainer);

    /**
     * Get the DOM element
     * @return {HTMLElement}
     */
    self.getElement = function () {
      return $helpTextDialogBox;
    };

    self.focus = function () {
      $closeButton.focus();
    };
  }

  JoubelHelpTextDialog.prototype = Object.create(H5P.EventDispatcher.prototype);
  JoubelHelpTextDialog.prototype.constructor = JoubelHelpTextDialog;

  return JoubelHelpTextDialog;
}(H5P.jQuery));
;var H5P = H5P || {};

/**
 * Class responsible for creating auto-disappearing dialogs
 */
H5P.JoubelMessageDialog = (function ($) {

  /**
   * Display a pop-up containing a message.
   *
   * @param {H5P.jQuery} $container The container which message dialog will be appended to
   * @param {string} message The message
   * @return {H5P.jQuery}
   */
  function JoubelMessageDialog ($container, message) {
    var timeout;

    var removeDialog = function () {
      $warning.remove();
      clearTimeout(timeout);
      $container.off('click.messageDialog');
    };

    // Create warning popup:
    var $warning = $('<div/>', {
      'class': 'joubel-message-dialog',
      text: message
    }).appendTo($container);

    // Remove after 3 seconds or if user clicks anywhere in $container:
    timeout = setTimeout(removeDialog, 3000);
    $container.on('click.messageDialog', removeDialog);

    return $warning;
  }

  return JoubelMessageDialog;
})(H5P.jQuery);
;var H5P = H5P || {};

/**
 * Class responsible for creating a circular progress bar
 */

H5P.JoubelProgressCircle = (function ($) {

  /**
   * Constructor for the Progress Circle
   *
   * @param {Number} number The amount of progress to display
   * @param {string} progressColor Color for the progress meter
   * @param {string} backgroundColor Color behind the progress meter
   */
  function ProgressCircle(number, progressColor, fillColor, backgroundColor) {
    progressColor = progressColor || '#1a73d9';
    fillColor = fillColor || '#f0f0f0';
    backgroundColor = backgroundColor || '#ffffff';
    var progressColorRGB = this.hexToRgb(progressColor);

    //Verify number
    try {
      number = Number(number);
      if (number === '') {
        throw 'is empty';
      }
      if (isNaN(number)) {
        throw 'is not a number';
      }
    } catch (e) {
      number = 'err';
    }

    //Draw circle
    if (number > 100) {
      number = 100;
    }

    // We can not use rgba, since they will stack on top of each other.
    // Instead we create the equivalent of the rgba color
    // and applies this to the activeborder and background color.
    var progressColorString = 'rgb(' + parseInt(progressColorRGB.r, 10) +
      ',' + parseInt(progressColorRGB.g, 10) +
      ',' + parseInt(progressColorRGB.b, 10) + ')';

    // Circle wrapper
    var $wrapper = $('<div/>', {
      'class': "joubel-progress-circle-wrapper"
    });

    //Active border indicates progress
    var $activeBorder = $('<div/>', {
      'class': "joubel-progress-circle-active-border"
    }).appendTo($wrapper);

    //Background circle
    var $backgroundCircle = $('<div/>', {
      'class': "joubel-progress-circle-circle"
    }).appendTo($activeBorder);

    //Progress text/number
    $('<span/>', {
      'text': number + '%',
      'class': "joubel-progress-circle-percentage"
    }).appendTo($backgroundCircle);

    var deg = number * 3.6;
    if (deg <= 180) {
      $activeBorder.css('background-image',
        'linear-gradient(' + (90 + deg) + 'deg, transparent 50%, ' + fillColor + ' 50%),' +
        'linear-gradient(90deg, ' + fillColor + ' 50%, transparent 50%)')
        .css('border', '2px solid' + backgroundColor)
        .css('background-color', progressColorString);
    } else {
      $activeBorder.css('background-image',
        'linear-gradient(' + (deg - 90) + 'deg, transparent 50%, ' + progressColorString + ' 50%),' +
        'linear-gradient(90deg, ' + fillColor + ' 50%, transparent 50%)')
        .css('border', '2px solid' + backgroundColor)
        .css('background-color', progressColorString);
    }

    this.$activeBorder = $activeBorder;
    this.$backgroundCircle = $backgroundCircle;
    this.$wrapper = $wrapper;

    this.initResizeFunctionality();

    return $wrapper;
  }

  /**
   * Initializes resize functionality for the progress circle
   */
  ProgressCircle.prototype.initResizeFunctionality = function () {
    var self = this;

    $(window).resize(function () {
      // Queue resize
      setTimeout(function () {
        self.resize();
      });
    });

    // First resize
    setTimeout(function () {
      self.resize();
    }, 0);
  };

  /**
   * Resize function makes progress circle grow or shrink relative to parent container
   */
  ProgressCircle.prototype.resize = function () {
    var $parent = this.$wrapper.parent();

    if ($parent !== undefined && $parent) {

      // Measurements
      var fontSize = parseInt($parent.css('font-size'), 10);

      // Static sizes
      var fontSizeMultiplum = 3.75;
      var progressCircleWidthPx = parseInt((fontSize / 4.5), 10) % 2 === 0 ? parseInt((fontSize / 4.5), 10) + 4 : parseInt((fontSize / 4.5), 10) + 5;
      var progressCircleOffset = progressCircleWidthPx / 2;

      var width = fontSize * fontSizeMultiplum;
      var height = fontSize * fontSizeMultiplum;
      this.$activeBorder.css({
        'width': width,
        'height': height
      });

      this.$backgroundCircle.css({
        'width': width - progressCircleWidthPx,
        'height': height - progressCircleWidthPx,
        'top': progressCircleOffset,
        'left': progressCircleOffset
      });
    }
  };

  /**
   * Hex to RGB conversion
   * @param hex
   * @returns {{r: Number, g: Number, b: Number}}
   */
  ProgressCircle.prototype.hexToRgb = function (hex) {
    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    return result ? {
      r: parseInt(result[1], 16),
      g: parseInt(result[2], 16),
      b: parseInt(result[3], 16)
    } : null;
  };

  return ProgressCircle;

}(H5P.jQuery));
;var H5P = H5P || {};

H5P.SimpleRoundedButton = (function ($) {

  /**
   * Creates a new tip
   */
  function SimpleRoundedButton(text) {

    var $simpleRoundedButton = $('<div>', {
      'class': 'joubel-simple-rounded-button',
      'title': text,
      'role': 'button',
      'tabindex': '0'
    }).keydown(function (e) {
      // 32 - space, 13 - enter
      if ([32, 13].indexOf(e.which) !== -1) {
        $(this).click();
        e.preventDefault();
      }
    });

    $('<span>', {
      'class': 'joubel-simple-rounded-button-text',
      'html': text
    }).appendTo($simpleRoundedButton);

    return $simpleRoundedButton;
  }

  return SimpleRoundedButton;
}(H5P.jQuery));
;var H5P = H5P || {};

/**
 * Class responsible for creating speech bubbles
 */
H5P.JoubelSpeechBubble = (function ($) {

  var $currentSpeechBubble;
  var $currentContainer;  
  var $tail;
  var $innerTail;
  var removeSpeechBubbleTimeout;
  var currentMaxWidth;

  var DEFAULT_MAX_WIDTH = 400;

  var iDevice = navigator.userAgent.match(/iPod|iPhone|iPad/g) ? true : false;

  /**
   * Creates a new speech bubble
   *
   * @param {H5P.jQuery} $container The speaking object
   * @param {string} text The text to display
   * @param {number} maxWidth The maximum width of the bubble
   * @return {H5P.JoubelSpeechBubble}
   */
  function JoubelSpeechBubble($container, text, maxWidth) {
    maxWidth = maxWidth || DEFAULT_MAX_WIDTH;
    currentMaxWidth = maxWidth;
    $currentContainer = $container;

    this.isCurrent = function ($tip) {
      return $tip.is($currentContainer);
    };

    this.remove = function () {
      remove();
    };

    var fadeOutSpeechBubble = function ($speechBubble) {
      if (!$speechBubble) {
        return;
      }

      // Stop removing bubble
      clearTimeout(removeSpeechBubbleTimeout);

      $speechBubble.removeClass('show');
      setTimeout(function () {
        if ($speechBubble) {
          $speechBubble.remove();
          $speechBubble = undefined;
        }
      }, 500);
    };

    if ($currentSpeechBubble !== undefined) {
      remove();
    }

    var $h5pContainer = getH5PContainer($container);

    // Make sure we fade out old speech bubble
    fadeOutSpeechBubble($currentSpeechBubble);

    // Create bubble
    $tail = $('<div class="joubel-speech-bubble-tail"></div>');
    $innerTail = $('<div class="joubel-speech-bubble-inner-tail"></div>');
    var $innerBubble = $(
      '<div class="joubel-speech-bubble-inner">' +
      '<div class="joubel-speech-bubble-text">' + text + '</div>' +
      '</div>'
    ).prepend($innerTail);

    $currentSpeechBubble = $(
      '<div class="joubel-speech-bubble" aria-live="assertive">'
    ).append([$tail, $innerBubble])
      .appendTo($h5pContainer);

    // Show speech bubble with transition
    setTimeout(function () {
      $currentSpeechBubble.addClass('show');
    }, 0);

    position($currentSpeechBubble, $currentContainer, maxWidth, $tail, $innerTail);

    // Handle click to close
    H5P.$body.on('mousedown.speechBubble', handleOutsideClick);

    // Handle window resizing
    H5P.$window.on('resize', '', handleResize);

    // Handle clicks when inside IV which blocks bubbling.
    $container.parents('.h5p-dialog')
      .on('mousedown.speechBubble', handleOutsideClick);

    if (iDevice) {
      H5P.$body.css('cursor', 'pointer');
    }

    return this;
  }

  // Remove speechbubble if it belongs to a dom element that is about to be hidden
  H5P.externalDispatcher.on('domHidden', function (event) {
    if ($currentSpeechBubble !== undefined && event.data.$dom.find($currentContainer).length !== 0) {
      remove();
    }
  });

  /**
   * Returns the closest h5p container for the given DOM element.
   * 
   * @param {object} $container jquery element
   * @return {object} the h5p container (jquery element)
   */
  function getH5PContainer($container) {
    var $h5pContainer = $container.closest('.h5p-frame');

    // Check closest h5p frame first, then check for container in case there is no frame.
    if (!$h5pContainer.length) {
      $h5pContainer = $container.closest('.h5p-container');
    }

    return $h5pContainer;
  }

  /**
   * Event handler that is called when the window is resized.
   */
  function handleResize() {
    position($currentSpeechBubble, $currentContainer, currentMaxWidth, $tail, $innerTail);
  }

  /**
   * Repositions the speech bubble according to the position of the container.
   * 
   * @param {object} $currentSpeechbubble the speech bubble that should be positioned   
   * @param {object} $container the container to which the speech bubble should point 
   * @param {number} maxWidth the maximum width of the speech bubble
   * @param {object} $tail the tail (the triangle that points to the referenced container)
   * @param {object} $innerTail the inner tail (the triangle that points to the referenced container)
   */
  function position($currentSpeechBubble, $container, maxWidth, $tail, $innerTail) {
    var $h5pContainer = getH5PContainer($container);

    // Calculate offset between the button and the h5p frame
    var offset = getOffsetBetween($h5pContainer, $container);

    var direction = (offset.bottom > offset.top ? 'bottom' : 'top');
    var tipWidth = offset.outerWidth * 0.9; // Var needs to be renamed to make sense
    var bubbleWidth = tipWidth > maxWidth ? maxWidth : tipWidth;

    var bubblePosition = getBubblePosition(bubbleWidth, offset);
    var tailPosition = getTailPosition(bubbleWidth, bubblePosition, offset, $container.width());
    // Need to set font-size, since element is appended to body.
    // Using same font-size as parent. In that way it will grow accordingly
    // when resizing
    var fontSize = 16;//parseFloat($parent.css('font-size'));

    // Set width and position of speech bubble
    $currentSpeechBubble.css(bubbleCSS(
      direction,
      bubbleWidth,
      bubblePosition,
      fontSize
    ));

    var preparedTailCSS = tailCSS(direction, tailPosition);
    $tail.css(preparedTailCSS);
    $innerTail.css(preparedTailCSS);
  }

  /**
   * Static function for removing the speechbubble
   */
  var remove = function () {
    H5P.$body.off('mousedown.speechBubble');
    H5P.$window.off('resize', '', handleResize);
    $currentContainer.parents('.h5p-dialog').off('mousedown.speechBubble');
    if (iDevice) {
      H5P.$body.css('cursor', '');
    }
    if ($currentSpeechBubble !== undefined) {
      // Apply transition, then remove speech bubble
      $currentSpeechBubble.removeClass('show');

      // Make sure we remove any old timeout before reassignment
      clearTimeout(removeSpeechBubbleTimeout);
      removeSpeechBubbleTimeout = setTimeout(function () {
        $currentSpeechBubble.remove();
        $currentSpeechBubble = undefined;
      }, 500);
    }
    // Don't return false here. If the user e.g. clicks a button when the bubble is visible,
    // we want the bubble to disapear AND the button to receive the event
  };

  /**
   * Remove the speech bubble and container reference
   */
  function handleOutsideClick(event) {
    if (event.target === $currentContainer[0]) {
      return; // Button clicks are not outside clicks
    }

    remove();
    // There is no current container when a container isn't clicked
    $currentContainer = undefined;
  }

  /**
   * Calculate position for speech bubble
   *
   * @param {number} bubbleWidth The width of the speech bubble
   * @param {object} offset
   * @return {object} Return position for the speech bubble
   */
  function getBubblePosition(bubbleWidth, offset) {
    var bubblePosition = {};

    var tailOffset = 9;
    var widthOffset = bubbleWidth / 2;

    // Calculate top position
    bubblePosition.top = offset.top + offset.innerHeight;

    // Calculate bottom position
    bubblePosition.bottom = offset.bottom + offset.innerHeight + tailOffset;

    // Calculate left position
    if (offset.left < widthOffset) {
      bubblePosition.left = 3;
    }
    else if ((offset.left + widthOffset) > offset.outerWidth) {
      bubblePosition.left = offset.outerWidth - bubbleWidth - 3;
    }
    else {
      bubblePosition.left = offset.left - widthOffset + (offset.innerWidth / 2);
    }

    return bubblePosition;
  }

  /**
   * Calculate position for speech bubble tail
   *
   * @param {number} bubbleWidth The width of the speech bubble
   * @param {object} bubblePosition Speech bubble position
   * @param {object} offset
   * @param {number} iconWidth The width of the tip icon
   * @return {object} Return position for the tail
   */
  function getTailPosition(bubbleWidth, bubblePosition, offset, iconWidth) {
    var tailPosition = {};
    // Magic numbers. Tuned by hand so that the tail fits visually within
    // the bounds of the speech bubble.
    var leftBoundary = 9;
    var rightBoundary = bubbleWidth - 20;

    tailPosition.left = offset.left - bubblePosition.left + (iconWidth / 2) - 6;
    if (tailPosition.left < leftBoundary) {
      tailPosition.left = leftBoundary;
    }
    if (tailPosition.left > rightBoundary) {
      tailPosition.left = rightBoundary;
    }

    tailPosition.top = -6;
    tailPosition.bottom = -6;

    return tailPosition;
  }

  /**
   * Return bubble CSS for the desired growth direction
   *
   * @param {string} direction The direction the speech bubble will grow
   * @param {number} width The width of the speech bubble
   * @param {object} position Speech bubble position
   * @param {number} fontSize The size of the bubbles font
   * @return {object} Return CSS
   */
  function bubbleCSS(direction, width, position, fontSize) {
    if (direction === 'top') {
      return {
        width: width + 'px',
        bottom: position.bottom + 'px',
        left: position.left + 'px',
        fontSize: fontSize + 'px',
        top: ''
      };
    }
    else {
      return {
        width: width + 'px',
        top: position.top + 'px',
        left: position.left + 'px',
        fontSize: fontSize + 'px',
        bottom: ''
      };
    }
  }

  /**
   * Return tail CSS for the desired growth direction
   *
   * @param {string} direction The direction the speech bubble will grow
   * @param {object} position Tail position
   * @return {object} Return CSS
   */
  function tailCSS(direction, position) {
    if (direction === 'top') {
      return {
        bottom: position.bottom + 'px',
        left: position.left + 'px',
        top: ''
      };
    }
    else {
      return {
        top: position.top + 'px',
        left: position.left + 'px',
        bottom: ''
      };
    }
  }

  /**
   * Calculates the offset between an element inside a container and the
   * container. Only works if all the edges of the inner element are inside the
   * outer element.
   * Width/height of the elements is included as a convenience.
   *
   * @param {H5P.jQuery} $outer
   * @param {H5P.jQuery} $inner
   * @return {object} Position offset
   */
  function getOffsetBetween($outer, $inner) {
    var outer = $outer[0].getBoundingClientRect();
    var inner = $inner[0].getBoundingClientRect();

    return {
      top: inner.top - outer.top,
      right: outer.right - inner.right,
      bottom: outer.bottom - inner.bottom,
      left: inner.left - outer.left,
      innerWidth: inner.width,
      innerHeight: inner.height,
      outerWidth: outer.width,
      outerHeight: outer.height
    };
  }

  return JoubelSpeechBubble;
})(H5P.jQuery);
;var H5P = H5P || {};

H5P.JoubelThrobber = (function ($) {

  /**
   * Creates a new tip
   */
  function JoubelThrobber() {

    // h5p-throbber css is described in core
    var $throbber = $('<div/>', {
      'class': 'h5p-throbber'
    });

    return $throbber;
  }

  return JoubelThrobber;
}(H5P.jQuery));
;H5P.JoubelTip = (function ($) {
  var $conv = $('<div/>');

  /**
   * Creates a new tip element.
   *
   * NOTE that this may look like a class but it doesn't behave like one.
   * It returns a jQuery object.
   *
   * @param {string} tipHtml The text to display in the popup
   * @param {Object} [behaviour] Options
   * @param {string} [behaviour.tipLabel] Set to use a custom label for the tip button (you want this for good A11Y)
   * @param {boolean} [behaviour.helpIcon] Set to 'true' to Add help-icon classname to Tip button (changes the icon)
   * @param {boolean} [behaviour.showSpeechBubble] Set to 'false' to disable functionality (you may this in the editor)
   * @param {boolean} [behaviour.tabcontrol] Set to 'true' if you plan on controlling the tabindex in the parent (tabindex="-1")
   * @return {H5P.jQuery|undefined} Tip button jQuery element or 'undefined' if invalid tip
   */
  function JoubelTip(tipHtml, behaviour) {

    // Keep track of the popup that appears when you click the Tip button
    var speechBubble;

    // Parse tip html to determine text
    var tipText = $conv.html(tipHtml).text().trim();
    if (tipText === '') {
      return; // The tip has no textual content, i.e. it's invalid.
    }

    // Set default behaviour
    behaviour = $.extend({
      tipLabel: tipText,
      helpIcon: false,
      showSpeechBubble: true,
      tabcontrol: false
    }, behaviour);

    // Create Tip button
    var $tipButton = $('<div/>', {
      class: 'joubel-tip-container' + (behaviour.showSpeechBubble ? '' : ' be-quiet'),
      'aria-label': behaviour.tipLabel,
      'aria-expanded': false,
      role: 'button',
      tabindex: (behaviour.tabcontrol ? -1 : 0),
      click: function (event) {
        // Toggle show/hide popup
        toggleSpeechBubble();
        event.preventDefault();
      },
      keydown: function (event) {
        if (event.which === 32 || event.which === 13) { // Space & enter key
          // Toggle show/hide popup
          toggleSpeechBubble();
          event.stopPropagation();
          event.preventDefault();
        }
        else { // Any other key
          // Toggle hide popup
          toggleSpeechBubble(false);
        }
      },
      // Add markup to render icon
      html: '<span class="joubel-icon-tip-normal ' + (behaviour.helpIcon ? ' help-icon': '') + '">' +
              '<span class="h5p-icon-shadow"></span>' +
              '<span class="h5p-icon-speech-bubble"></span>' +
              '<span class="h5p-icon-info"></span>' +
            '</span>'
      // IMPORTANT: All of the markup elements must have 'pointer-events: none;'
    });

    const $tipAnnouncer = $('<div>', {
      'class': 'hidden-but-read',
      'aria-live': 'polite',
      appendTo: $tipButton,
    });

    /**
     * Tip button interaction handler.
     * Toggle show or hide the speech bubble popup when interacting with the
     * Tip button.
     *
     * @private
     * @param {boolean} [force] 'true' shows and 'false' hides.
     */
    var toggleSpeechBubble = function (force) {
      if (speechBubble !== undefined && speechBubble.isCurrent($tipButton)) {
        // Hide current popup
        speechBubble.remove();
        speechBubble = undefined;

        $tipButton.attr('aria-expanded', false);
        $tipAnnouncer.html('');
      }
      else if (force !== false && behaviour.showSpeechBubble) {
        // Create and show new popup
        speechBubble = H5P.JoubelSpeechBubble($tipButton, tipHtml);
        $tipButton.attr('aria-expanded', true);
        $tipAnnouncer.html(tipHtml);
      }
    };

    return $tipButton;
  }

  return JoubelTip;
})(H5P.jQuery);
;var H5P = H5P || {};

H5P.JoubelSlider = (function ($) {

  /**
   * Creates a new Slider
   *
   * @param {object} [params] Additional parameters
   */
  function JoubelSlider(params) {
    H5P.EventDispatcher.call(this);

    this.$slider = $('<div>', $.extend({
      'class': 'h5p-joubel-ui-slider'
    }, params));

    this.$slides = [];
    this.currentIndex = 0;
    this.numSlides = 0;
  }
  JoubelSlider.prototype = Object.create(H5P.EventDispatcher.prototype);
  JoubelSlider.prototype.constructor = JoubelSlider;

  JoubelSlider.prototype.addSlide = function ($content) {
    $content.addClass('h5p-joubel-ui-slide').css({
      'left': (this.numSlides*100) + '%'
    });
    this.$slider.append($content);
    this.$slides.push($content);

    this.numSlides++;

    if(this.numSlides === 1) {
      $content.addClass('current');
    }
  };

  JoubelSlider.prototype.attach = function ($container) {
    $container.append(this.$slider);
  };

  JoubelSlider.prototype.move = function (index) {
    var self = this;

    if(index === 0) {
      self.trigger('first-slide');
    }
    if(index+1 === self.numSlides) {
      self.trigger('last-slide');
    }
    self.trigger('move');

    var $previousSlide = self.$slides[this.currentIndex];
    H5P.Transition.onTransitionEnd(this.$slider, function () {
      $previousSlide.removeClass('current');
      self.trigger('moved');
    });
    this.$slides[index].addClass('current');

    var translateX = 'translateX(' + (-index*100) + '%)';
    this.$slider.css({
      '-webkit-transform': translateX,
      '-moz-transform': translateX,
      '-ms-transform': translateX,
      'transform': translateX
    });

    this.currentIndex = index;
  };

  JoubelSlider.prototype.remove = function () {
    this.$slider.remove();
  };

  JoubelSlider.prototype.next = function () {
    if(this.currentIndex+1 >= this.numSlides) {
      return;
    }

    this.move(this.currentIndex+1);
  };

  JoubelSlider.prototype.previous = function () {
    this.move(this.currentIndex-1);
  };

  JoubelSlider.prototype.first = function () {
    this.move(0);
  };

  JoubelSlider.prototype.last = function () {
    this.move(this.numSlides-1);
  };

  return JoubelSlider;
})(H5P.jQuery);
;var H5P = H5P || {};

/**
 * @module
 */
H5P.JoubelScoreBar = (function ($) {

  /* Need to use an id for the star SVG since that is the only way to reference
     SVG filters  */
  var idCounter = 0;

  /**
   * Creates a score bar
   * @class H5P.JoubelScoreBar
   * @param {number} maxScore  Maximum score
   * @param {string} [label] Makes it easier for readspeakers to identify the scorebar
   * @param {string} [helpText] Score explanation
   * @param {string} [scoreExplanationButtonLabel] Label for score explanation button
   */
  function JoubelScoreBar(maxScore, label, helpText, scoreExplanationButtonLabel) {
    var self = this;

    self.maxScore = maxScore;
    self.score = 0;
    idCounter++;

    /**
     * @const {string}
     */
    self.STAR_MARKUP = '<svg tabindex="-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 63.77 53.87" aria-hidden="true" focusable="false">' +
        '<title>star</title>' +
        '<filter tabindex="-1" id="h5p-joubelui-score-bar-star-inner-shadow-' + idCounter + '" x0="-50%" y0="-50%" width="200%" height="200%">' +
          '<feGaussianBlur in="SourceAlpha" stdDeviation="3" result="blur"></feGaussianBlur>' +
          '<feOffset dy="2" dx="4"></feOffset>' +
          '<feComposite in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowDiff"></feComposite>' +
          '<feFlood flood-color="#ffe95c" flood-opacity="1"></feFlood>' +
          '<feComposite in2="shadowDiff" operator="in"></feComposite>' +
          '<feComposite in2="SourceGraphic" operator="over" result="firstfilter"></feComposite>' +
          '<feGaussianBlur in="firstfilter" stdDeviation="3" result="blur2"></feGaussianBlur>' +
          '<feOffset dy="-2" dx="-4"></feOffset>' +
          '<feComposite in2="firstfilter" operator="arithmetic" k2="-1" k3="1" result="shadowDiff"></feComposite>' +
          '<feFlood flood-color="#ffe95c" flood-opacity="1"></feFlood>' +
          '<feComposite in2="shadowDiff" operator="in"></feComposite>' +
          '<feComposite in2="firstfilter" operator="over"></feComposite>' +
        '</filter>' +
        '<path tabindex="-1" class="h5p-joubelui-score-bar-star-shadow" d="M35.08,43.41V9.16H20.91v0L9.51,10.85,9,10.93C2.8,12.18,0,17,0,21.25a11.22,11.22,0,0,0,3,7.48l8.73,8.53-1.07,6.16Z"/>' +
        '<g tabindex="-1">' +
          '<path tabindex="-1" class="h5p-joubelui-score-bar-star-border" d="M61.36,22.8,49.72,34.11l2.78,16a2.6,2.6,0,0,1,.05.64c0,.85-.37,1.6-1.33,1.6A2.74,2.74,0,0,1,49.94,52L35.58,44.41,21.22,52a2.93,2.93,0,0,1-1.28.37c-.91,0-1.33-.75-1.33-1.6,0-.21.05-.43.05-.64l2.78-16L9.8,22.8A2.57,2.57,0,0,1,9,21.25c0-1,1-1.33,1.81-1.49l16.07-2.35L34.09,2.83c.27-.59.85-1.33,1.55-1.33s1.28.69,1.55,1.33l7.21,14.57,16.07,2.35c.75.11,1.81.53,1.81,1.49A3.07,3.07,0,0,1,61.36,22.8Z"/>' +
          '<path tabindex="-1" class="h5p-joubelui-score-bar-star-fill" d="M61.36,22.8,49.72,34.11l2.78,16a2.6,2.6,0,0,1,.05.64c0,.85-.37,1.6-1.33,1.6A2.74,2.74,0,0,1,49.94,52L35.58,44.41,21.22,52a2.93,2.93,0,0,1-1.28.37c-.91,0-1.33-.75-1.33-1.6,0-.21.05-.43.05-.64l2.78-16L9.8,22.8A2.57,2.57,0,0,1,9,21.25c0-1,1-1.33,1.81-1.49l16.07-2.35L34.09,2.83c.27-.59.85-1.33,1.55-1.33s1.28.69,1.55,1.33l7.21,14.57,16.07,2.35c.75.11,1.81.53,1.81,1.49A3.07,3.07,0,0,1,61.36,22.8Z"/>' +
          '<path tabindex="-1" filter="url(#h5p-joubelui-score-bar-star-inner-shadow-' + idCounter + ')" class="h5p-joubelui-score-bar-star-fill-full-score" d="M61.36,22.8,49.72,34.11l2.78,16a2.6,2.6,0,0,1,.05.64c0,.85-.37,1.6-1.33,1.6A2.74,2.74,0,0,1,49.94,52L35.58,44.41,21.22,52a2.93,2.93,0,0,1-1.28.37c-.91,0-1.33-.75-1.33-1.6,0-.21.05-.43.05-.64l2.78-16L9.8,22.8A2.57,2.57,0,0,1,9,21.25c0-1,1-1.33,1.81-1.49l16.07-2.35L34.09,2.83c.27-.59.85-1.33,1.55-1.33s1.28.69,1.55,1.33l7.21,14.57,16.07,2.35c.75.11,1.81.53,1.81,1.49A3.07,3.07,0,0,1,61.36,22.8Z"/>' +
        '</g>' +
      '</svg>';

    /**
     * @function appendTo
     * @memberOf H5P.JoubelScoreBar#
     * @param {H5P.jQuery}  $wrapper  Dom container
     */
    self.appendTo = function ($wrapper) {
      self.$scoreBar.appendTo($wrapper);
    };

    /**
     * Create the text representation of the scorebar .
     *
     * @private
     * @return {string}
     */
    var createLabel = function (score) {
      if (!label) {
        return '';
      }

      return label.replace(':num', score).replace(':total', self.maxScore);
    };

    /**
     * Creates the html for this widget
     *
     * @method createHtml
     * @private
     */
    var createHtml = function () {
      // Container div
      self.$scoreBar = $('<div>', {
        'class': 'h5p-joubelui-score-bar',
      });

      var $visuals = $('<div>', {
        'class': 'h5p-joubelui-score-bar-visuals',
        appendTo: self.$scoreBar
      });

      // The progress bar wrapper
      self.$progressWrapper = $('<div>', {
        'class': 'h5p-joubelui-score-bar-progress-wrapper',
        appendTo: $visuals
      });

      self.$progress = $('<div>', {
        'class': 'h5p-joubelui-score-bar-progress',
        'html': createLabel(self.score),
        appendTo: self.$progressWrapper
      });

      // The star
      $('<div>', {
        'class': 'h5p-joubelui-score-bar-star',
        html: self.STAR_MARKUP
      }).appendTo($visuals);

      // The score container
      var $numerics = $('<div>', {
        'class': 'h5p-joubelui-score-numeric',
        appendTo: self.$scoreBar,
        'aria-hidden': true
      });

      // The current score
      self.$scoreCounter = $('<span>', {
        'class': 'h5p-joubelui-score-number h5p-joubelui-score-number-counter',
        text: 0,
        appendTo: $numerics
      });

      // The separator
      $('<span>', {
        'class': 'h5p-joubelui-score-number-separator',
        text: '/',
        appendTo: $numerics
      });

      // Max score
      self.$maxScore = $('<span>', {
        'class': 'h5p-joubelui-score-number h5p-joubelui-score-max',
        text: self.maxScore,
        appendTo: $numerics
      });

      if (helpText) {
        H5P.JoubelUI.createTip(helpText, {
          tipLabel: scoreExplanationButtonLabel ? scoreExplanationButtonLabel : helpText,
          helpIcon: true
        }).appendTo(self.$scoreBar);
        self.$scoreBar.addClass('h5p-score-bar-has-help');
      }
    };

    /**
     * Set the current score
     * @method setScore
     * @memberOf H5P.JoubelScoreBar#
     * @param  {number} score
     */
    self.setScore = function (score) {
      // Do nothing if score hasn't changed
      if (score === self.score) {
        return;
      }
      self.score = score > self.maxScore ? self.maxScore : score;
      self.updateVisuals();
    };

    /**
     * Increment score
     * @method incrementScore
     * @memberOf H5P.JoubelScoreBar#
     * @param  {number=}        incrementBy Optional parameter, defaults to 1
     */
    self.incrementScore = function (incrementBy) {
      self.setScore(self.score + (incrementBy || 1));
    };

    /**
     * Set the max score
     * @method setMaxScore
     * @memberOf H5P.JoubelScoreBar#
     * @param  {number}    maxScore The max score
     */
    self.setMaxScore = function (maxScore) {
      self.maxScore = maxScore;
    };

    /**
     * Updates the progressbar visuals
     * @memberOf H5P.JoubelScoreBar#
     * @method updateVisuals
     */
    self.updateVisuals = function () {
      self.$progress.html(createLabel(self.score));
      self.$scoreCounter.text(self.score);
      self.$maxScore.text(self.maxScore);

      setTimeout(function () {
        // Start the progressbar animation
        self.$progress.css({
          width: ((self.score / self.maxScore) * 100) + '%'
        });

        H5P.Transition.onTransitionEnd(self.$progress, function () {
          // If fullscore fill the star and start the animation
          self.$scoreBar.toggleClass('h5p-joubelui-score-bar-full-score', self.score === self.maxScore);
          self.$scoreBar.toggleClass('h5p-joubelui-score-bar-animation-active', self.score === self.maxScore);

          // Only allow the star animation to run once
          self.$scoreBar.one("animationend", function() {
            self.$scoreBar.removeClass("h5p-joubelui-score-bar-animation-active");
          });
        }, 600);
      }, 300);
    };

    /**
     * Removes all classes
     * @method reset
     */
    self.reset = function () {
      self.$scoreBar.removeClass('h5p-joubelui-score-bar-full-score');
    };

    createHtml();
  }

  return JoubelScoreBar;
})(H5P.jQuery);
;var H5P = H5P || {};

H5P.JoubelProgressbar = (function ($) {

  /**
   * Joubel progressbar class
   * @method JoubelProgressbar
   * @constructor
   * @param  {number}          steps Number of steps
   * @param {Object} [options] Additional options
   * @param {boolean} [options.disableAria] Disable readspeaker assistance
   * @param {string} [options.progressText] A progress text for describing
   *  current progress out of total progress for readspeakers.
   *  e.g. "Slide :num of :total"
   */
  function JoubelProgressbar(steps, options) {
    H5P.EventDispatcher.call(this);
    var self = this;
    this.options = $.extend({
      progressText: 'Slide :num of :total'
    }, options);
    this.currentStep = 0;
    this.steps = steps;

    this.$progressbar = $('<div>', {
      'class': 'h5p-joubelui-progressbar'
    });
    this.$background = $('<div>', {
      'class': 'h5p-joubelui-progressbar-background'
    }).appendTo(this.$progressbar);
  }

  JoubelProgressbar.prototype = Object.create(H5P.EventDispatcher.prototype);
  JoubelProgressbar.prototype.constructor = JoubelProgressbar;

  JoubelProgressbar.prototype.updateAria = function () {
    var self = this;
    if (this.options.disableAria) {
      return;
    }

    if (!this.$currentStatus) {
      this.$currentStatus = $('<div>', {
        'class': 'h5p-joubelui-progressbar-slide-status-text',
        'aria-live': 'assertive'
      }).appendTo(this.$progressbar);
    }
    var interpolatedProgressText = self.options.progressText
      .replace(':num', self.currentStep)
      .replace(':total', self.steps);
    this.$currentStatus.html(interpolatedProgressText);
  };

  /**
   * Appends to a container
   * @method appendTo
   * @param  {H5P.jquery} $container
   */
  JoubelProgressbar.prototype.appendTo = function ($container) {
    this.$progressbar.appendTo($container);
  };

  /**
   * Update progress
   * @method setProgress
   * @param  {number}    step
   */
  JoubelProgressbar.prototype.setProgress = function (step) {
    // Check for valid value:
    if (step > this.steps || step < 0) {
      return;
    }
    this.currentStep = step;
    this.$background.css({
      width: ((this.currentStep/this.steps)*100) + '%'
    });

    this.updateAria();
  };

  /**
   * Increment progress with 1
   * @method next
   */
  JoubelProgressbar.prototype.next = function () {
    this.setProgress(this.currentStep+1);
  };

  /**
   * Reset progressbar
   * @method reset
   */
  JoubelProgressbar.prototype.reset = function () {
    this.setProgress(0);
  };

  /**
   * Check if last step is reached
   * @method isLastStep
   * @return {Boolean}
   */
  JoubelProgressbar.prototype.isLastStep = function () {
    return this.steps === this.currentStep;
  };

  return JoubelProgressbar;
})(H5P.jQuery);
;var H5P = H5P || {};

/**
 * H5P Joubel UI library.
 *
 * This is a utility library, which does not implement attach. I.e, it has to bee actively used by
 * other libraries
 * @module
 */
H5P.JoubelUI = (function ($) {

  /**
   * The internal object to return
   * @class H5P.JoubelUI
   * @static
   */
  function JoubelUI() {}

  /* Public static functions */

  /**
   * Create a tip icon
   * @method H5P.JoubelUI.createTip
   * @param  {string}  text   The textual tip
   * @param  {Object}  params Parameters
   * @return {H5P.JoubelTip}
   */
  JoubelUI.createTip = function (text, params) {
    return new H5P.JoubelTip(text, params);
  };

  /**
   * Create message dialog
   * @method H5P.JoubelUI.createMessageDialog
   * @param  {H5P.jQuery}               $container The dom container
   * @param  {string}                   message    The message
   * @return {H5P.JoubelMessageDialog}
   */
  JoubelUI.createMessageDialog = function ($container, message) {
    return new H5P.JoubelMessageDialog($container, message);
  };

  /**
   * Create help text dialog
   * @method H5P.JoubelUI.createHelpTextDialog
   * @param  {string}             header  The textual header
   * @param  {string}             message The textual message
   * @param  {string}             closeButtonTitle The title for the close button
   * @return {H5P.JoubelHelpTextDialog}
   */
  JoubelUI.createHelpTextDialog = function (header, message, closeButtonTitle) {
    return new H5P.JoubelHelpTextDialog(header, message, closeButtonTitle);
  };

  /**
   * Create progress circle
   * @method H5P.JoubelUI.createProgressCircle
   * @param  {number}             number          The progress (0 to 100)
   * @param  {string}             progressColor   The progress color in hex value
   * @param  {string}             fillColor       The fill color in hex value
   * @param  {string}             backgroundColor The background color in hex value
   * @return {H5P.JoubelProgressCircle}
   */
  JoubelUI.createProgressCircle = function (number, progressColor, fillColor, backgroundColor) {
    return new H5P.JoubelProgressCircle(number, progressColor, fillColor, backgroundColor);
  };

  /**
   * Create throbber for loading
   * @method H5P.JoubelUI.createThrobber
   * @return {H5P.JoubelThrobber}
   */
  JoubelUI.createThrobber = function () {
    return new H5P.JoubelThrobber();
  };

  /**
   * Create simple rounded button
   * @method H5P.JoubelUI.createSimpleRoundedButton
   * @param  {string}                  text The button label
   * @return {H5P.SimpleRoundedButton}
   */
  JoubelUI.createSimpleRoundedButton = function (text) {
    return new H5P.SimpleRoundedButton(text);
  };

  /**
   * Create Slider
   * @method H5P.JoubelUI.createSlider
   * @param  {Object} [params] Parameters
   * @return {H5P.JoubelSlider}
   */
  JoubelUI.createSlider = function (params) {
    return new H5P.JoubelSlider(params);
  };

  /**
   * Create Score Bar
   * @method H5P.JoubelUI.createScoreBar
   * @param  {number=}       maxScore The maximum score
   * @param {string} [label] Makes it easier for readspeakers to identify the scorebar
   * @return {H5P.JoubelScoreBar}
   */
  JoubelUI.createScoreBar = function (maxScore, label, helpText, scoreExplanationButtonLabel) {
    return new H5P.JoubelScoreBar(maxScore, label, helpText, scoreExplanationButtonLabel);
  };

  /**
   * Create Progressbar
   * @method H5P.JoubelUI.createProgressbar
   * @param  {number=}       numSteps The total numer of steps
   * @param {Object} [options] Additional options
   * @param {boolean} [options.disableAria] Disable readspeaker assistance
   * @param {string} [options.progressText] A progress text for describing
   *  current progress out of total progress for readspeakers.
   *  e.g. "Slide :num of :total"
   * @return {H5P.JoubelProgressbar}
   */
  JoubelUI.createProgressbar = function (numSteps, options) {
    return new H5P.JoubelProgressbar(numSteps, options);
  };

  /**
   * Create standard Joubel button
   *
   * @method H5P.JoubelUI.createButton
   * @param {object} params
   *  May hold any properties allowed by jQuery. If href is set, an A tag
   *  is used, if not a button tag is used.
   * @return {H5P.jQuery} The jquery element created
   */
  JoubelUI.createButton = function(params) {
    var type = 'button';
    if (params.href) {
      type = 'a';
    }
    else {
      params.type = 'button';
    }
    if (params.class) {
      params.class += ' h5p-joubelui-button';
    }
    else {
      params.class = 'h5p-joubelui-button';
    }
    return $('<' + type + '/>', params);
  };

  /**
   * Fix for iframe scoll bug in IOS. When focusing an element that doesn't have
   * focus support by default the iframe will scroll the parent frame so that
   * the focused element is out of view. This varies dependening on the elements
   * of the parent frame.
   */
  if (H5P.isFramed && !H5P.hasiOSiframeScrollFix &&
      /iPad|iPhone|iPod/.test(navigator.userAgent)) {
    H5P.hasiOSiframeScrollFix = true;

    // Keep track of original focus function
    var focus = HTMLElement.prototype.focus;

    // Override the original focus
    HTMLElement.prototype.focus = function () {
      // Only focus the element if it supports it natively
      if ( (this instanceof HTMLAnchorElement ||
            this instanceof HTMLInputElement ||
            this instanceof HTMLSelectElement ||
            this instanceof HTMLTextAreaElement ||
            this instanceof HTMLButtonElement ||
            this instanceof HTMLIFrameElement ||
            this instanceof HTMLAreaElement) && // HTMLAreaElement isn't supported by Safari yet.
          !this.getAttribute('role')) { // Focus breaks if a different role has been set
          // In theory this.isContentEditable should be able to recieve focus,
          // but it didn't work when tested.

        // Trigger the original focus with the proper context
        focus.call(this);
      }
    };
  }

  return JoubelUI;
})(H5P.jQuery);
;(()=>{"use strict";var r=H5P.jQuery,e=function(){function e(e,t,a,i){var s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{},n=arguments.length>5?arguments[5]:void 0;return this.card=e,this.params=t||{},this.id=a,this.contentId=i,this.callbacks=s,this.$cardWrapper=r("<div>",{class:"h5p-dialogcards-cardwrap",role:"group",tabindex:"-1"}),this.$cardWrapper.addClass("h5p-dialogcards-mode-"+this.params.mode),"repetition"!==this.params.mode&&this.$cardWrapper.attr("aria-labelledby","h5p-dialogcards-progress-"+n),this.$cardHolder=r("<div>",{class:"h5p-dialogcards-cardholder"}).appendTo(this.$cardWrapper),this.createCardContent(e).appendTo(this.$cardHolder),this}var t=e.prototype;return t.createCardContent=function(e){var t=r("<div>",{class:"h5p-dialogcards-card-content"});this.createCardImage(e).appendTo(t);var a=r("<div>",{class:"h5p-dialogcards-card-text-wrapper"}).appendTo(t),i=r("<div>",{class:"h5p-dialogcards-card-text-inner"}).appendTo(a),s=r("<div>",{class:"h5p-dialogcards-card-text-inner-content"}).appendTo(i);this.createCardAudio(e).appendTo(s);var n=r("<div>",{class:"h5p-dialogcards-card-text"}).appendTo(s);return this.$cardTextArea=r("<div>",{class:"h5p-dialogcards-card-text-area",tabindex:"-1",html:e.text}).appendTo(n),e.text&&e.text.length||n.addClass("hide"),this.createCardFooter().appendTo(a),t},t.massageAttributeOutput=function(r){var e=(new DOMParser).parseFromString(r,"text/html"),t=document.createElement("div");return t.innerHTML=e.documentElement.textContent,t.textContent||t.innerText||""},t.createCardImage=function(e){this.$image;var t=r("<div>",{class:"h5p-dialogcards-image-wrapper"});return void 0!==e.image?(this.image=e.image,this.$image=r('<img class="h5p-dialogcards-image" src="'+H5P.getPath(e.image.path,this.contentId)+'"/>'),e.imageAltText&&this.$image.attr("alt",this.massageAttributeOutput(e.imageAltText))):this.$image=r('<div class="h5p-dialogcards-image"></div>'),this.$image.appendTo(t),t},t.createCardAudio=function(e){if(this.audio,this.$audioWrapper=r("<div>",{class:"h5p-dialogcards-audio-wrapper"}),void 0!==e.audio){var t={files:e.audio,audioNotSupported:this.params.audioNotSupported};this.audio=new H5P.Audio(t,this.contentId),this.audio.attach(this.$audioWrapper),this.audio.audio&&this.audio.audio.preload&&(this.audio.audio.preload="none")}else this.$audioWrapper.addClass("hide");return this.$audioWrapper},t.createCardFooter=function(){var e=r("<div>",{class:"h5p-dialogcards-card-footer"}),t="h5p-dialogcards-button-hidden",a="-1";return"repetition"===this.params.mode&&(t="",this.params.behaviour.quickProgression&&(t="h5p-dialogcards-quick-progression",a="0")),this.$buttonTurn=H5P.JoubelUI.createButton({class:"h5p-dialogcards-turn",html:this.params.answer}).appendTo(e),"repetition"===this.params.mode&&(this.$buttonShowSummary=H5P.JoubelUI.createButton({class:"h5p-dialogcards-show-summary h5p-dialogcards-button-gone",html:this.params.showSummary}).appendTo(e),this.$buttonIncorrect=H5P.JoubelUI.createButton({class:"h5p-dialogcards-answer-button",html:this.params.incorrectAnswer}).addClass("incorrect").addClass(t).attr("tabindex",a).appendTo(e),this.$buttonCorrect=H5P.JoubelUI.createButton({class:"h5p-dialogcards-answer-button",html:this.params.correctAnswer}).addClass("correct").addClass(t).attr("tabindex",a).appendTo(e)),e},t.createButtonListeners=function(){var r=this;this.$buttonTurn.unbind("click").click((function(){r.turnCard()})),"repetition"===this.params.mode&&(this.$buttonIncorrect.unbind("click").click((function(e){e.target.classList.contains("h5p-dialogcards-quick-progression")&&r.callbacks.onNextCard({cardId:r.id,result:!1})})),this.$buttonCorrect.unbind("click").click((function(e){e.target.classList.contains("h5p-dialogcards-quick-progression")&&r.callbacks.onNextCard({cardId:r.id,result:!0})})))},t.showSummaryButton=function(r){this.getDOM().find(".h5p-dialogcards-answer-button").addClass("h5p-dialogcards-button-hidden").attr("tabindex","-1"),this.$buttonTurn.addClass("h5p-dialogcards-button-gone"),this.$buttonShowSummary.click((function(){return r()})).removeClass("h5p-dialogcards-button-gone").focus()},t.hideSummaryButton=function(){"normal"!==this.params.mode&&(this.getDOM().find(".h5p-dialogcards-answer-button").removeClass("h5p-dialogcards-button-hidden").attr("tabindex","0"),this.$buttonTurn.removeClass("h5p-dialogcards-button-gone"),this.$buttonShowSummary.addClass("h5p-dialogcards-button-gone").off("click"))},t.turnCard=function(){var r=this,e=this.getDOM(),t=e.find(".h5p-dialogcards-card-content"),a=e.find(".h5p-dialogcards-cardholder").addClass("h5p-dialogcards-collapse");t.find(".joubel-tip-container").remove();var i=t.hasClass("h5p-dialogcards-turned");t.toggleClass("h5p-dialogcards-turned",!i),this.isInTransition=!0,setTimeout((function(){if(a.removeClass("h5p-dialogcards-collapse"),r.changeText(i?r.getText():r.getAnswer()),i?a.find(".h5p-audio-inner").removeClass("hide"):r.removeAudio(a),"repetition"===r.params.mode&&!r.params.behaviour.quickProgression){var s=e.find(".h5p-dialogcards-answer-button");!1===s.hasClass("h5p-dialogcards-quick-progression")&&s.addClass("h5p-dialogcards-quick-progression").attr("tabindex",0)}setTimeout((function(){r.isInTransition=!1,r.addTipToCard(t,i?"front":"back"),"function"==typeof r.callbacks.onCardTurned&&r.callbacks.onCardTurned(i)}),200),r.resizeOverflowingText(),r.$cardTextArea.focus()}),200)},t.changeText=function(r){this.$cardTextArea.html(r),this.$cardTextArea.toggleClass("hide",!r||!r.length)},t.setProgressText=function(r,e){if("repetition"===this.params.mode){var t=this.params.progressText.replace("@card",r.toString()).replace("@total",e.toString());this.$cardWrapper.attr("aria-label",t)}},t.resizeOverflowingText=function(){if(this.params.behaviour.scaleTextNotCard){var r=this.getDOM().find(".h5p-dialogcards-card-text"),e=r.children();this.resizeTextToFitContainer(r,e)}},t.resizeTextToFitContainer=function(r,t){t.css("font-size","");var a=r.get(0).getBoundingClientRect().height,i=t.get(0).getBoundingClientRect().height,s=parseFloat(r.css("font-size")),n=parseFloat(t.css("font-size")),o=this.getDOM().closest(".h5p-container"),d=parseFloat(o.css("font-size"));if(i>a)for(var c=!0;c;){if((n-=e.SCALEINTERVAL)<e.MINSCALE){c=!1;break}t.css("font-size",n/s+"em"),(i=t.get(0).getBoundingClientRect().height)<=a&&(c=!1)}else for(var l=!0;l;){if((n+=e.SCALEINTERVAL)>d){l=!1;break}t.css("font-size",n/s+"em"),(i=t.get(0).getBoundingClientRect().height)>=a&&(l=!1,n-=e.SCALEINTERVAL,t.css("font-size",n/s+"em"))}},t.addTipToCard=function(r,e,t){"back"!==e&&(e="front"),void 0===t&&(t=this.id),r.find(".joubel-tip-container").remove();var a=this.card.tips;if(void 0!==a&&void 0!==a[e]){var i=a[e].trim();i.length&&r.find(".h5p-dialogcards-card-text-wrapper .h5p-dialogcards-card-text-inner").after(H5P.JoubelUI.createTip(i,{tipLabel:this.params.tipButtonLabel}))}},t.setCardFocus=function(r){if(!0===r)this.$cardTextArea.focus();else{var e=this.getDOM();e.one("transitionend",(function(){e.focus()}))}},t.stopAudio=function(){var r=this;if(this.audio&&this.audio.audio){var e=this.audio.audio.duration;e>0&&e<Number.MAX_SAFE_INTEGER&&this.audio.seekTo(e),this.audio.audio.load&&setTimeout((function(){r.audio.audio.load()}),100)}},t.removeAudio=function(){this.stopAudio(),this.getDOM().find(".h5p-audio-inner").addClass("hide")},t.getDOM=function(){return this.$cardWrapper},t.getText=function(){return this.card.text},t.getAnswer=function(){return this.card.answer},t.getImage=function(){return this.$image},t.getImageSize=function(){return this.image?{width:this.image.width,height:this.image.height}:this.image},t.getAudio=function(){return this.$audioWrapper},t.reset=function(){var r=this.getDOM();r.removeClass("h5p-dialogcards-previous"),r.removeClass("h5p-dialogcards-current"),this.changeText(this.getText());var e=r.find(".h5p-dialogcards-card-content");e.removeClass("h5p-dialogcards-turned"),this.addTipToCard(e,"front",this.id),this.params.behaviour.quickProgression||r.find(".h5p-dialogcards-answer-button").removeClass("h5p-dialogcards-quick-progression"),this.hideSummaryButton()},e}();e.SCALEINTERVAL=.2,e.MAXSCALE=16,e.MINSCALE=4;const t=e;const a=function(){function r(r,e,t,a){var i=this;return this.params=r,this.contentId=e,this.callbacks=t,this.idCounter=a,this.cards=[],this.params.dialogs.forEach((function(r,e){r.id=e,i.cards.push(e)})),this}var e=r.prototype;return e.getCard=function(r){if(!(r<0||r>this.cards.length))return"number"==typeof this.cards[r]&&this.loadCard(r),this.cards[r]},e.getCardIds=function(){return this.cards.map((function(r,e){return e}))},e.loadCard=function(r){r<0||r>this.cards.length||"number"==typeof this.cards[r]&&(this.cards[r]=new t(this.params.dialogs[r],this.params,r,this.contentId,this.callbacks,this.idCounter))},r}();function i(r){return function(r){if(Array.isArray(r))return s(r)}(r)||function(r){if("undefined"!=typeof Symbol&&null!=r[Symbol.iterator]||null!=r["@@iterator"])return Array.from(r)}(r)||function(r,e){if(r){if("string"==typeof r)return s(r,e);var t={}.toString.call(r).slice(8,-1);return"Object"===t&&r.constructor&&(t=r.constructor.name),"Map"===t||"Set"===t?Array.from(r):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?s(r,e):void 0}}(r)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function s(r,e){(null==e||e>r.length)&&(e=r.length);for(var t=0,a=Array(e);t<e;t++)a[t]=r[t];return a}const n=function(){function r(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];return this.cards=r.filter((function(e,t){return r.indexOf(e)>=t})),this}var e=r.prototype;return e.getCards=function(){return this.cards},e.peek=function(r){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return e=Math.max(0,e),"top"===r&&(r=0),"bottom"===r&&(r=this.cards.length-e),r<0||r>this.cards.length-1?[]:this.cards.slice(r,r+e)},e.add=function(r){var e=this,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"top";"number"==typeof r&&(r=[r]),r.forEach((function(a){var s;-1===e.cards.indexOf(a)&&("top"===t?t=0:"bottom"===t?t=e.cards.length:"random"===t&&(t=Math.floor(Math.random()*e.cards.length)),(s=e.cards).splice.apply(s,[t,0].concat(i(r))))}))},e.push=function(r){this.add(r,"top")},e.pull=function(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"top";return r=Math.max(1,Math.min(r,this.cards.length)),"top"===e&&(e=0),"bottom"===e&&(e=-r),e=Math.max(0,Math.min(e,this.cards.length-1)),this.cards.splice(e,r)},e.remove=function(r){var e=this;"number"==typeof r&&(r=[r]),r.forEach((function(r){var t=e.cards.indexOf(r);t>-1&&e.cards.splice(t,1)}))},e.shuffle=function(){for(var r=this.cards.length-1;r>0;r--){var e=Math.floor(Math.random()*(r+1)),t=[this.cards[e],this.cards[r]];this.cards[r]=t[0],this.cards[e]=t[1]}return this.cards},e.contains=function(r){return-1!==this.cards.indexOf(r)},e.length=function(){return this.cards.length},r}();function o(r){return function(r){if(Array.isArray(r))return d(r)}(r)||function(r){if("undefined"!=typeof Symbol&&null!=r[Symbol.iterator]||null!=r["@@iterator"])return Array.from(r)}(r)||function(r,e){if(r){if("string"==typeof r)return d(r,e);var t={}.toString.call(r).slice(8,-1);return"Object"===t&&r.constructor&&(t=r.constructor.name),"Map"===t||"Set"===t?Array.from(r):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?d(r,e):void 0}}(r)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function d(r,e){(null==e||e>r.length)&&(e=r.length);for(var t=0,a=Array(e);t<e;t++)a[t]=r[t];return a}const c=function(){function r(r,e,t,i){return this.params=r,this.cardPool=new a(r,e,t,i),this.reset(r.cardPiles),this}var e=r.prototype;return e.createSelection=function(){var r=[];if("repetition"===this.params.mode)r=this.createSelectionRepetition();else r=this.cardPool.getCardIds();return r},e.createPiles=function(r){if(r)this.cardPiles=r.map((function(r){return new n(r.cards)}));else{this.cardPiles=[];var e=this.cardPool.getCardIds();switch(this.params.mode){case"repetition":for(var t=0;t<this.params.behaviour.maxProficiency+1;t++)0===t?this.cardPiles.push(new n(e)):this.cardPiles.push(new n);break;case"normal":this.cardPiles.push(new n(e))}}},e.updatePiles=function(r){var e=this;return r.forEach((function(r){var t=e.find(r.cardId);if(-1!==t){var a=!0===r.result?t+1:0;a=Math.max(0,Math.min(a,e.cardPiles.length-1)),e.cardPiles[t].remove(r.cardId),e.cardPiles[a].add(r.cardId,"bottom")}})),this.getPileSizes()},e.createSelectionRepetition=function(){for(var r=[],e=null,t=0;t<this.cardPiles.length-1;t++){var a,i=this.cardPiles[t].length();if(null!==e||0!==i){null===e&&(e=t);var s=Math.ceil(1*i/(1+t-e)),n=this.cardPiles[t].peek(0,s);r=(a=r).concat.apply(a,o(n))}}return r=this.shuffle(r)},e.shuffle=function(r){for(var e=r.slice(),t=e.length-1;t>0;t--){var a=Math.floor(Math.random()*(t+1)),i=[e[a],e[t]];e[t]=i[0],e[a]=i[1]}return e},e.find=function(r){var e=-1;return this.cardPiles.forEach((function(t,a){if(-1!==e)return e;t.contains(r)&&(e=a)})),e},e.reset=function(r){this.createPiles(r)},e.getCard=function(r){return this.cardPool.getCard(r)},e.getSize=function(){return this.cardPool.getCardIds().length},e.getPiles=function(){return this.cardPiles},e.getPileSizes=function(){return this.cardPiles.map((function(r){return r.length()}))},r}();const l=function(){function r(r,e){var t=this;this.params=r,this.callbacks=e,this.currentCallback=e.nextRound,this.fields=[],this.container=document.createElement("div"),this.container.classList.add("h5p-dialogcards-summary-screen");var a=this.createContainerDOM(r.summary);this.fields.round=a.getElementsByClassName("h5p-dialogcards-summary-subheader")[0],this.fields["h5p-dialogcards-round-cards-right"]=this.addTableRow(a,{category:this.params.summaryCardsRight,symbol:"h5p-dialogcards-check"}),this.fields["h5p-dialogcards-round-cards-wrong"]=this.addTableRow(a,{category:this.params.summaryCardsWrong,symbol:"h5p-dialogcards-times"}),this.fields["h5p-dialogcards-round-cards-not-shown"]=this.addTableRow(a,{category:this.params.summaryCardsNotShown});var i=this.createContainerDOM(r.summaryOverallScore);this.fields["h5p-dialogcards-overall-cards-completed"]=this.addTableRow(i,{category:this.params.summaryCardsCompleted,symbol:"h5p-dialogcards-check"}),this.fields["h5p-dialogcards-overall-completed-rounds"]=this.addTableRow(i,{category:this.params.summaryCompletedRounds,symbol:""});var s=document.createElement("div");s.classList.add("h5p-dialogcards-summary-message"),this.fields.message=s;var n=H5P.JoubelUI.createButton({class:"h5p-dialogcards-buttonNextRound",title:this.params.nextRound.replace("@round",2),html:this.params.nextRound.replace("@round",2)}).click(this.currentCallback).get(0);this.fields.button=n;var o=H5P.JoubelUI.createButton({class:"h5p-dialogcards-button-restart",title:this.params.startOver,html:this.params.startOver}).get(0),d=this.createConfirmationDialog({l10n:this.params.confirmStartingOver,instance:this},(function(){setTimeout((function(){t.callbacks.retry()}),100)}));o.addEventListener("click",(function(r){d.show(r.target.offsetTop)})),this.fields.buttonStartOver=o;var c=document.createElement("div");return c.classList.add("h5p-dialogcards-summary-footer"),c.appendChild(o),c.appendChild(n),this.container.appendChild(a),this.container.appendChild(i),this.container.appendChild(s),this.container.appendChild(c),this.hide(),this}var e=r.prototype;return e.getDOM=function(){return this.container},e.createContainerDOM=function(r){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",t=document.createElement("div");t.classList.add("h5p-dialogcards-summary-container");var a=document.createElement("div");a.classList.add("h5p-dialogcards-summary-header"),a.innerHTML=r,t.appendChild(a);var i=document.createElement("div");i.classList.add("h5p-dialogcards-summary-subheader"),i.innerHTML=e,t.appendChild(i);var s=document.createElement("table");return s.classList.add("h5p-dialogcards-summary-table"),t.appendChild(s),t},e.addTableRow=function(r,e){var t=r.getElementsByClassName("h5p-dialogcards-summary-table")[0],a=document.createElement("tr"),i=document.createElement("td");i.classList.add("h5p-dialogcards-summary-table-row-category"),i.innerHTML=e.category,a.appendChild(i);var s=document.createElement("td");s.classList.add("h5p-dialogcards-summary-table-row-symbol"),void 0!==e.symbol&&""!==e.symbol&&s.classList.add(e.symbol),a.appendChild(s);var n=document.createElement("td");return n.classList.add("h5p-dialogcards-summary-table-row-score"),a.appendChild(n),t.appendChild(a),n},e.update=function(){var r=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.done,a=void 0!==t&&t,i=e.round,s=void 0===i?void 0:i,n=e.message,o=void 0===n?void 0:n,d=e.results,c=void 0===d?[]:d;!0===a?(this.fields.buttonStartOver.classList.add("h5p-dialogcards-button-gone"),this.params.behaviour.enableRetry?(this.fields.button.classList.remove("h5p-dialogcards-button-next-round"),this.fields.button.classList.add("h5p-dialogcards-button-restart"),this.fields.button.innerHTML=this.params.retry,this.fields.button.title=this.params.retry,this.currentCallback=this.callbacks.retry):this.fields.button.classList.add("h5p-dialogcards-button-gone")):(this.fields.buttonStartOver.classList.remove("h5p-dialogcards-button-gone"),this.fields.button.classList.add("h5p-dialogcards-button-next-round"),this.fields.button.classList.remove("h5p-dialogcards-button-restart"),this.fields.button.innerHTML=this.params.nextRound,this.fields.button.title=this.params.nextRound,this.currentCallback=this.callbacks.nextRound),H5P.jQuery(this.fields.button).unbind("click").click(this.currentCallback),this.fields.round.innerHTML=this.params.round.replace("@round",s),a||void 0===s||(this.fields.button.innerHTML=this.params.nextRound.replace("@round",s+1),this.fields.button.title=this.params.nextRound.replace("@round",s+1)),a&&void 0!==o&&""!==o?(this.fields.message.classList.remove("h5p-dialogcards-gone"),this.fields.message.innerHTML=o):this.fields.message.classList.add("h5p-dialogcards-gone"),c.forEach((function(e){var t=void 0!==e.score.value?e.score.value:"";void 0!==e.score.max&&(t="".concat(t,'&nbsp;<span class="h5p-dialogcards-summary-table-row-score-divider">/</span>&nbsp;').concat(e.score.max)),r.fields[e.field].innerHTML=t}))},e.show=function(){var r=this;this.container.classList.remove("h5p-dialogcards-gone"),setTimeout((function(){r.fields.button.focus()}),0)},e.hide=function(){this.container.classList.add("h5p-dialogcards-gone")},e.createConfirmationDialog=function(r,e){r=r||{};var t=new H5P.ConfirmationDialog({instance:r.instance,headerText:r.l10n.header,dialogText:r.l10n.body,cancelText:r.l10n.cancelLabel,confirmText:r.l10n.confirmLabel});return t.on("confirmed",(function(){e()})),t.appendTo(this.getContainer()),t},e.getContainer=function(){var r=H5P.jQuery('[data-content-id="'+self.contentId+'"].h5p-content'),e=r.parents(".h5p-container");return(0!==e.length?e.last():0!==r.length?r:H5P.jQuery(document.body)).get(0)},r}();function u(r){if(void 0===r)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return r}function h(r,e){return h=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(r,e){return r.__proto__=e,r},h(r,e)}var p=H5P.jQuery,g=H5P.JoubelUI,m=function(r){var e,t;function a(e,t,i){var s;return(s=r.call(this)||this).idCounter=a.idCounter++,s.contentId=s.id=t,s.previousState=i.previousState||{},s.contentData=i||{},s.params=p.extend({title:"",mode:"normal",description:"",next:"Next",prev:"Previous",retry:"Retry",answer:"Turn",correctAnswer:"I got it right!",incorrectAnswer:"I got it wrong",round:"Round @round",cardsLeft:"Cards left: @number",nextRound:"Proceed to round @round",startOver:"Start over",showSummary:"Next",summary:"Summary",summaryCardsRight:"Cards you got right:",summaryCardsWrong:"Cards you got wrong:",summaryCardsNotShown:"Cards in pool not shown:",summaryOverallScore:"Overall Score",summaryCardsCompleted:"Cards you have completed learning:",summaryCompletedRounds:"Completed rounds:",summaryAllDone:"Well done! You have mastered all @cards cards by getting them correct @max times!",progressText:"Card @card of @total",cardFrontLabel:"Card front",cardBackLabel:"Card back",tipButtonLabel:"Show tip",audioNotSupported:"Your browser does not support this audio",confirmStartingOver:{header:"Start over?",body:"All progress will be lost. Are you sure you want to start over?",cancelLabel:"Cancel",confirmLabel:"Start over"},dialogs:[{text:"Horse",answer:"Hest"},{text:"Cow",answer:"Ku"}],behaviour:{enableRetry:!0,disableBackwardsNavigation:!1,scaleTextNotCard:!1,randomCards:!1,maxProficiency:5,quickProgression:!1}},e),s.cards=[],s.currentCardId=0,s.round=0,s.results=s.previousState.results||[],s.attach=function(r){s.$inner=r.addClass("h5p-dialogcards"),s.params.behaviour.scaleTextNotCard&&r.addClass("h5p-text-scaling");var e={mode:s.params.mode,dialogs:s.params.dialogs,audioNotSupported:s.params.audioNotSupported,answer:s.params.answer,showSummary:s.params.showSummary,incorrectAnswer:s.params.incorrectAnswer,correctAnswer:s.params.correctAnswer,progressText:s.params.progressText,tipButtonLabel:s.params.tipButtonLabel,behaviour:{scaleTextNotCard:s.params.behaviour.scaleTextNotCard,maxProficiency:s.params.behaviour.maxProficiency,quickProgression:s.params.behaviour.quickProgression},cardPiles:s.previousState.cardPiles};s.cardManager=new c(e,s.id,{onCardTurned:s.handleCardTurned,onNextCard:s.nextCard},s.idCounter),s.createDOM(0===s.round),void 0!==s.previousState.currentCardId&&(s.gotoCard(s.previousState.currentCardId),"repetition"===s.params.mode&&s.results.length===s.cardIds.length&&s.showSummary(!0)),s.updateNavigation(),s.trigger("resize")},s.createDOM=function(r){if(s.cardIds=r&&s.previousState.cardIds?s.previousState.cardIds:s.cardManager.createSelection(),s.cardPoolSize=s.cardPoolSize||s.cardManager.getSize(),!0===r){var e=p("<div>"+s.params.title+"</div>").text().trim();s.$header=p((e?'<div class="h5p-dialogcards-title"><div class="h5p-dialogcards-title-inner">'+s.params.title+"</div></div>":"")+'<div class="h5p-dialogcards-description">'+s.params.description+"</div>"),s.summaryScreen=new l(s.params,{nextRound:s.nextRound,retry:s.restartRepetition})}!0===r?s.$cardwrapperSet=s.initCards(s.cardIds):(s.$cardwrapperSet.detach(),s.$cardwrapperSet=s.initCards(s.cardIds),s.$cardSideAnnouncer.before(s.$cardwrapperSet)),s.$cardwrapperSet.prepend(s.summaryScreen.getDOM()),!0===r&&(s.$cardSideAnnouncer=p("<div>",{html:s.params.cardFrontLabel,class:"h5p-dialogcards-card-side-announcer","aria-live":"polite"}),s.$footer=s.createFooter(),s.$mainContent=p("<div>").append(s.$header).append(s.$cardwrapperSet).append(s.$cardSideAnnouncer).append(s.$footer).appendTo(s.$inner),s.on("reset",(function(){this.reset()})),s.on("resize",s.resize),s.round=void 0!==s.previousState.round?s.previousState.round:1)},s.createFooter=function(){var r=p("<nav>",{class:"h5p-dialogcards-footer",role:"navigation"}),e=function(r,e){p(r).append('<span class="button-tooltip">'+e+"</span>"),p(r).find(".button-tooltip").hide().fadeIn("fast")},t=function(r){p(r).find(".button-tooltip").remove()};if("normal"===s.params.mode){var a=u(s);s.$prev=g.createButton({class:"h5p-dialogcards-footer-button h5p-dialogcards-prev truncated","aria-label":s.params.prev}).click((function(){s.prevCard()})).appendTo(r),s.$prev.hover((function(r){e(a.$prev,a.params.prev)}),(function(){t(a.$prev)})),s.$next=g.createButton({class:"h5p-dialogcards-footer-button h5p-dialogcards-next truncated","aria-label":s.params.next}).click((function(){s.nextCard()})).appendTo(r),s.$next.hover((function(r){e(a.$next,a.params.next)}),(function(){t(a.$next)})),s.$retry=g.createButton({class:"h5p-dialogcards-footer-button h5p-dialogcards-retry h5p-dialogcards-disabled",html:s.params.retry}).click((function(){s.trigger("reset")})).appendTo(r),s.$retry.hover((function(r){e(a.$retry,a.params.retry)}),(function(){t(a.$retry)})),s.$progress=p("<div>",{id:"h5p-dialogcards-progress-"+s.idCounter,class:"h5p-dialogcards-progress","aria-live":"assertive"}).appendTo(r)}else s.$round=p("<div>",{class:"h5p-dialogcards-round"}).appendTo(r),s.$progress=p("<div>",{class:"h5p-dialogcards-cards-left","aria-live":"assertive"}).appendTo(r);return r},s.updateImageSize=function(){var r=0,e=s.cards[s.currentCardId].getDOM().find(".h5p-dialogcards-card-content");if(s.params.dialogs.forEach((function(t){if(t.image){var a=t.image.height/t.image.width*e.get(0).getBoundingClientRect().width;a>r&&(r=a)}})),r>0){var t=r/parseFloat(s.$inner.css("font-size"));t>15&&(t=15),s.cards.forEach((function(r){r.getImage().parent().css("height",t+"em")}))}},s.initCards=function(r){s.cards=[],s.currentCardId=0,s.params.behaviour.randomCards&&(r=H5P.shuffleArray(r));for(var e=p("<div>",{class:"h5p-dialogcards-cardwrap-set"}),t=0;t<r.length&&!(t>=2);t++){var a=s.getCard(r[t]);a.setProgressText(t+1,r.length),s.cards.push(a);var i=a.getDOM();t===s.currentCardId&&(i.addClass("h5p-dialogcards-current"),s.$current=i),a.addTipToCard(i.find(".h5p-dialogcards-card-content"),"front",t),e.append(i)}return e},s.handleCardTurned=function(r){s.$cardSideAnnouncer.html(r?s.params.cardFrontLabel:s.params.cardBackLabel),s.params.behaviour.enableRetry&&s.currentCardId+1===s.cardIds.length&&s.$retry&&(s.$retry.removeClass("h5p-dialogcards-disabled"),s.truncateRetryButton())},s.updateNavigation=function(){if("normal"===s.params.mode)s.getCurrentSelectionIndex()<s.cardIds.length-1?(s.$next.removeClass("h5p-dialogcards-disabled"),s.$retry.addClass("h5p-dialogcards-disabled")):s.$next.addClass("h5p-dialogcards-disabled"),s.currentCardId>0&&!s.params.behaviour.disableBackwardsNavigation?s.$prev.removeClass("h5p-dialogcards-disabled"):s.$prev.addClass("h5p-dialogcards-disabled"),s.$progress.text(s.params.progressText.replace("@card",s.getCurrentSelectionIndex()+1).replace("@total",s.cardIds.length)),s.cards[s.findCardPosition(s.cards[s.currentCardId].id)].resizeOverflowingText();else{s.$round.text(s.params.round.replace("@round",s.round));var r=s.getCurrentSelectionIndex();s.$progress.text(s.params.cardsLeft.replace("@number",s.cardIds.length-r))}s.trigger("resize")},s.showSummary=function(){var r=arguments.length>0&&void 0!==arguments[0]&&arguments[0]?s.cardManager.getPileSizes():s.cardManager.updatePiles(s.results),e=s.results.filter((function(r){return!0===r.result})).length,t=s.results.length-e,a=s.cardPoolSize-e-t,i=r.slice(-1)[0],n=i===s.cardPoolSize,o={round:s.round,results:[{field:"h5p-dialogcards-round-cards-right",score:{value:e,max:t+e}},{field:"h5p-dialogcards-round-cards-wrong",score:{value:t,max:t+e}},{field:"h5p-dialogcards-round-cards-not-shown",score:{value:a}},{field:"h5p-dialogcards-overall-cards-completed",score:{value:i,max:s.cardPoolSize}},{field:"h5p-dialogcards-overall-completed-rounds",score:{value:s.round}}]};n&&(o.done=!0,o.message=s.params.summaryAllDone.replace("@cards",s.cardPoolSize).replace("@max",s.params.behaviour.maxProficiency)),s.summaryScreen.update(o),s.summaryScreen.show(),s.hideCards(),s.trigger("resize")},s.showCards=function(){s.$cardwrapperSet.find(".h5p-dialogcards-cardwrap").removeClass("h5p-dialogcards-gone"),s.$footer.removeClass("h5p-dialogcards-gone"),s.cardsShown=!0},s.hideCards=function(){s.$cardwrapperSet.find(".h5p-dialogcards-cardwrap").addClass("h5p-dialogcards-gone"),s.$footer.addClass("h5p-dialogcards-gone"),s.cardsShown=!1},s.nextCard=function(r){void 0!==r&&s.results.push(r),s.cards[s.currentCardId].stopAudio(),s.cardIds.length-s.getCurrentSelectionIndex()!=1?s.gotoCard(s.getCurrentSelectionIndex()+1):"repetition"===s.params.mode&&(s.$progress.text(s.params.cardsLeft.replace("@number",0)),s.cards[s.currentCardId].showSummaryButton(s.showSummary))},s.getCard=function(r){var e=s.cardManager.getCard(r);return e.createButtonListeners(),e},s.findCardPosition=function(r){var e;return s.cards.forEach((function(t,a){e||t.id!==r||(e=a)})),e},s.insertCardToDOM=function(r,e){var t=r.getDOM();void 0===e?t.appendTo(s.$cardwrapperSet):0===e?s.$cardwrapperSet.prepend(t):s.$cardwrapperSet.children().eq(e).after(t),r.addTipToCard(t.find(".h5p-dialogcards-card-content"),"front",e)},s.gotoCard=function(r){if(!(r<0||r>=s.cardIds.length)){var e=s.cards[s.currentCardId];e.stopAudio(),e.getDOM().removeClass("h5p-dialogcards-current");var t=[];r>0&&t.push(r-1),t.push(r),r+1<s.cardIds.length&&t.push(r+1),t.forEach((function(r){if(void 0===s.findCardPosition(s.cardIds[r])){var e=s.getCard(s.cardIds[r]);e.setProgressText(r+1,s.cardIds.length);var t=Math.min(r+1,s.cardIds.length-1),a=s.findCardPosition(s.cardIds[t])||s.cards.length;s.cards.splice(a,0,e),s.insertCardToDOM(e,a)}})),s.resize(),r=s.findCardPosition(s.cardIds[r]),s.cards.forEach((function(e,t){t<r?e.getDOM().addClass("h5p-dialogcards-previous"):(e.getDOM().removeClass("h5p-dialogcards-previous"),t===r&&e.getDOM().addClass("h5p-dialogcards-current"))})),s.currentCardId=r,s.updateNavigation(),s.cards[s.currentCardId].setCardFocus()}},s.prevCard=function(){s.gotoCard(s.getCurrentSelectionIndex()-1)},s.showAllAudio=function(){s.$cardwrapperSet.find(".h5p-audio-inner").removeClass("hide")},s.restartRepetition=function(){s.cardManager.reset(),s.round=0,s.nextRound()},s.nextRound=function(){var r=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];s.round++,s.summaryScreen.hide(),s.showCards(),s.reset(),s.createDOM(),s.updateNavigation(),(s.isRoot()||r)&&s.cards[s.currentCardId].setCardFocus(!0),s.trigger("resize")},s.reset=function(){s.results=[],s.cards[s.currentCardId].stopAudio(s.$current.index()),s.cards.forEach((function(r){r.reset()})),s.currentCardId=0,"normal"===s.params.mode&&s.cards[s.currentCardId].getDOM().addClass("h5p-dialogcards-current"),s.updateNavigation(),s.$retry&&s.$retry.addClass("h5p-dialogcards-disabled"),s.showAllAudio(),s.cards[s.currentCardId].resizeOverflowingText(),s.cards[s.currentCardId].setCardFocus()},s.resize=function(){if(s.cards[s.currentCardId].isInTransition||s.resizeTimeout)s.resizeTimeout=setTimeout((function(){delete s.resizeTimeout,s.resize()}),400);else{var r=0;s.updateImageSize(),s.params.behaviour.scaleTextNotCard||!1===s.cardsShown||s.determineCardSizes(),s.$cardwrapperSet.css("height","auto"),s.$cardwrapperSet.children(":not(.h5p-dialogcards-gone)").each((function(){var e=p(this).css("height","initial").outerHeight();if(p(this).css("height","inherit"),r=e>r?e:r,!p(this).next(".h5p-dialogcards-cardwrap").length){var t=p(this).find(".h5p-dialogcards-cardholder").css("height","initial").outerHeight();r=t>r?t:r,p(this).find(".h5p-dialogcards-cardholder").css("height","inherit")}}));var e=r/parseFloat(s.$cardwrapperSet.css("font-size"));s.$cardwrapperSet.css("height",e+"em"),s.scaleToFitHeight(),s.truncateRetryButton(),s.cards[s.currentCardId].resizeOverflowingText()}},s.determineCardSizes=function(){var r=u(s);void 0===s.cardSizeDetermined&&(s.cardSizeDetermined=[]),s.$cardwrapperSet.children(":visible").each((function(e){var t=r.cards[e].id;if(-1===r.cardSizeDetermined.indexOf(t)){r.cardSizeDetermined.push(t);var a=p(".h5p-dialogcards-card-content",this),i=p(".h5p-dialogcards-card-text-inner-content",a),s=i[0].getBoundingClientRect().height,n=r.cards[e];n.changeText(n.getAnswer());var o=i[0].getBoundingClientRect().height,d=s>o?s:o,c=parseFloat(i.parent().parent().css("minHeight"));d<c&&(d=c),d/=parseFloat(a.css("fontSize")),i.parent().css("height",d+"em"),n.changeText(n.getText())}}))},s.scaleToFitHeight=function(){if(s.$cardwrapperSet&&s.$cardwrapperSet.is(":visible")&&s.params.behaviour.scaleTextNotCard)if(s.$inner.parents(".h5p-course-presentation").length){var r=s.$inner.parent();s.$inner.parents(".h5p-popup-container").length&&(r=s.$inner.parents(".h5p-popup-container"));var e=r.get(0).getBoundingClientRect().height,t=function(){var r=0;return s.$inner.children().each((function(){var e=p(this);r+=this.getBoundingClientRect().height+parseFloat(e.css("margin-top"))+parseFloat(e.css("margin-bottom"))})),r},i=t(),n=parseFloat(s.$inner.parent().css("font-size")),o=parseFloat(s.$inner.css("font-size"));if(e<i)for(;e<i&&!((o-=a.SCALEINTERVAL)<a.MINSCALE);)s.$inner.css("font-size",o/n+"em"),i=t();else for(var d=!0;d;){if((o+=a.SCALEINTERVAL)>a.MAXSCALE){d=!1;break}var c=o/n;s.$inner.css("font-size",c+"em"),e<=(i=t())&&(d=!1,c=(o-a.SCALEINTERVAL)/n,s.$inner.css("font-size",c+"em"))}}else s.cards[s.currentCardId].resizeOverflowingText()},s.truncateRetryButton=function(){if(s.$retry){s.$retry.removeClass("truncated"),s.$retry.html(s.params.retry);(s.$retry.get(0).getBoundingClientRect().width+parseFloat(s.$retry.css("margin-left"))+parseFloat(s.$retry.css("margin-right")))/s.$retry.parent().get(0).getBoundingClientRect().width>.3&&(s.$retry.addClass("truncated"),s.$retry.html(""))}},s.getCurrentSelectionIndex=function(){return s.cardIds.indexOf(s.cards[s.currentCardId].id)},s.getTitle=function(){return H5P.createTitle(s.contentData&&s.contentData.metadata&&s.contentData.metadata.title?s.contentData.metadata.title:"Dialog Cards")},s.getCurrentState=function(){if(s.cardManager)return s.isProgressStarted()?{cardPiles:s.cardManager.getPiles(),cardIds:s.cardIds,round:s.round,currentCardId:s.getCurrentSelectionIndex(),results:s.results}:void 0},s.isProgressStarted=function(){return!H5P.isEmpty(s.previousState)||0!==s.getCurrentSelectionIndex()||0!==s.results.length||1!==s.round},s.resetTask=function(){var r=arguments.length>0&&void 0!==arguments[0]&&arguments[0];s.cardManager&&(s.previousState={},s.round=0,s.nextRound(r))},s}return t=r,(e=a).prototype=Object.create(t.prototype),e.prototype.constructor=e,h(e,t),a}(H5P.EventDispatcher);m.idCounter=0,m.SCALEINTERVAL=.2,m.MAXSCALE=16,m.MINSCALE=4;const f=m;H5P.Dialogcards=f})();;		(function(xopen, fetch, dataurls) {

			switch(location.protocol.split(':')[0]) {
				case 'http':
				case 'https':
					return;
			};

			const url2data	= function(oldurl) {
					switch(oldurl.split(':')[0]) {
						case 'blob':
							console.log('blob', oldurl);
						case 'data':
							return oldurl;
					}
					let urltoks	 = oldurl.replace(H5PIntegration.url, '.').split('/');
					if(urltoks[0] == '.') {
						urltoks.shift();
						const url	= urltoks.join('/');
						if(typeof dataurls[url]!=='undefined') {
							if(dataurls[url][0]=='application/json') {
								return 'data:application/json;text,' + dataurls[url][1];
							}
							return 'data:' + dataurls[url].join(';base64,');
						}
					}
					console.error('url not found:', oldurl);
					return "data:;text,";
			};
			window.fetch = function() {
				arguments[0]	= url2data(arguments[0]);
				return fetch.apply(this, arguments);
			};
			XMLHttpRequest.prototype.open = function() {
				arguments[1]	= url2data(arguments[1]);
				return xopen.apply(this, arguments);
			};
		})(XMLHttpRequest.prototype.open, window.fetch, {"libraries\/H5P.Dialogcards-1.9\/library.json":["application\/json","{\"title\":\"Dialog Cards\",\"description\":\"Makes it possible to create learning tasks for your site visitors.\",\"majorVersion\":1,\"minorVersion\":9,\"patchVersion\":18,\"runnable\":1,\"author\":\"Joubel\",\"license\":\"MIT\",\"machineName\":\"H5P.Dialogcards\",\"coreApi\":{\"majorVersion\":1,\"minorVersion\":26},\"embedTypes\":[\"iframe\"],\"preloadedCss\":[{\"path\":\"dist\\\/h5p-dialogcards.css\"}],\"preloadedJs\":[{\"path\":\"dist\\\/h5p-dialogcards.js\"}],\"preloadedDependencies\":[{\"machineName\":\"FontAwesome\",\"majorVersion\":4,\"minorVersion\":5},{\"machineName\":\"H5P.JoubelUI\",\"majorVersion\":1,\"minorVersion\":3},{\"machineName\":\"H5P.Audio\",\"majorVersion\":1,\"minorVersion\":5}],\"editorDependencies\":[{\"machineName\":\"H5PEditor.VerticalTabs\",\"majorVersion\":1,\"minorVersion\":3},{\"machineName\":\"H5PEditor.ShowWhen\",\"majorVersion\":1,\"minorVersion\":0}]}"],"libraries\/FontAwesome-4.5\/library.json":["application\/json","{\"title\":\"Font Awesome\",\"contentType\":\"Font\",\"majorVersion\":4,\"minorVersion\":5,\"patchVersion\":6,\"runnable\":0,\"machineName\":\"FontAwesome\",\"license\":\"MIT\",\"author\":\"Dave Gandy\",\"preloadedCss\":[{\"path\":\"h5p-font-awesome.min.css\"}]}"],"libraries\/H5P.JoubelUI-1.3\/library.json":["application\/json","{\"title\":\"Joubel UI\",\"contentType\":\"Utility\",\"description\":\"UI utility library\",\"majorVersion\":1,\"minorVersion\":3,\"patchVersion\":19,\"runnable\":0,\"coreApi\":{\"majorVersion\":1,\"minorVersion\":3},\"machineName\":\"H5P.JoubelUI\",\"author\":\"Joubel\",\"preloadedJs\":[{\"path\":\"js\\\/joubel-help-dialog.js\"},{\"path\":\"js\\\/joubel-message-dialog.js\"},{\"path\":\"js\\\/joubel-progress-circle.js\"},{\"path\":\"js\\\/joubel-simple-rounded-button.js\"},{\"path\":\"js\\\/joubel-speech-bubble.js\"},{\"path\":\"js\\\/joubel-throbber.js\"},{\"path\":\"js\\\/joubel-tip.js\"},{\"path\":\"js\\\/joubel-slider.js\"},{\"path\":\"js\\\/joubel-score-bar.js\"},{\"path\":\"js\\\/joubel-progressbar.js\"},{\"path\":\"js\\\/joubel-ui.js\"}],\"preloadedCss\":[{\"path\":\"css\\\/joubel-help-dialog.css\"},{\"path\":\"css\\\/joubel-message-dialog.css\"},{\"path\":\"css\\\/joubel-progress-circle.css\"},{\"path\":\"css\\\/joubel-simple-rounded-button.css\"},{\"path\":\"css\\\/joubel-speech-bubble.css\"},{\"path\":\"css\\\/joubel-tip.css\"},{\"path\":\"css\\\/joubel-slider.css\"},{\"path\":\"css\\\/joubel-score-bar.css\"},{\"path\":\"css\\\/joubel-progressbar.css\"},{\"path\":\"css\\\/joubel-ui.css\"},{\"path\":\"css\\\/joubel-icon.css\"}],\"preloadedDependencies\":[{\"machineName\":\"FontAwesome\",\"majorVersion\":4,\"minorVersion\":5},{\"machineName\":\"H5P.Transition\",\"majorVersion\":1,\"minorVersion\":0},{\"machineName\":\"H5P.FontIcons\",\"majorVersion\":1,\"minorVersion\":0}]}"],"libraries\/H5P.Transition-1.0\/library.json":["application\/json","{\"machineName\":\"H5P.Transition\",\"title\":\"Transition\",\"description\":\"Contains helper function relevant for transitioning\",\"license\":\"MIT\",\"author\":\"Joubel\",\"majorVersion\":1,\"minorVersion\":0,\"patchVersion\":4,\"runnable\":0,\"preloadedJs\":[{\"path\":\"transition.js\"}]}"],"libraries\/H5P.FontIcons-1.0\/library.json":["application\/json","{\"title\":\"H5P.FontIcons\",\"majorVersion\":1,\"minorVersion\":0,\"patchVersion\":11,\"runnable\":0,\"machineName\":\"H5P.FontIcons\",\"author\":\"Joubel\",\"preloadedCss\":[{\"path\":\"styles\\\/h5p-font-icons.css\"}]}"],"libraries\/H5P.Audio-1.5\/library.json":["application\/json","{\"title\":\"Audio\",\"contentType\":\"Media\",\"description\":\"Simple library that displays an audio player.\",\"majorVersion\":1,\"minorVersion\":5,\"patchVersion\":12,\"runnable\":1,\"machineName\":\"H5P.Audio\",\"embedTypes\":[\"iframe\"],\"author\":\"Joubel\",\"coreApi\":{\"majorVersion\":1,\"minorVersion\":19},\"preloadedJs\":[{\"path\":\"scripts\\\/audio.js\"}],\"preloadedCss\":[{\"path\":\"styles\\\/audio.css\"}],\"preloadedDependencies\":[{\"machineName\":\"FontAwesome\",\"majorVersion\":4,\"minorVersion\":5}],\"editorDependencies\":[{\"machineName\":\"H5PEditor.ShowWhen\",\"majorVersion\":1,\"minorVersion\":0}]}"],"libraries\/H5PEditor.ShowWhen-1.0\/library.json":["application\/json","{\"machineName\":\"H5PEditor.ShowWhen\",\"title\":\"Toggle visibility of a field based on rules\",\"license\":\"MIT\",\"author\":\"fnoks\",\"majorVersion\":1,\"minorVersion\":0,\"patchVersion\":9,\"runnable\":0,\"preloadedJs\":[{\"path\":\"h5p-show-when.js\"}],\"preloadedCss\":[{\"path\":\"h5p-show-when.css\"}]}"],"libraries\/H5PEditor.VerticalTabs-1.3\/library.json":["application\/json","{\"machineName\":\"H5PEditor.VerticalTabs\",\"title\":\"H5P Editor Vertical Tabs\",\"license\":\"MIT\",\"author\":\"Joubel\",\"majorVersion\":1,\"minorVersion\":3,\"patchVersion\":14,\"runnable\":0,\"coreApi\":{\"majorVersion\":1,\"minorVersion\":24},\"preloadedJs\":[{\"path\":\"vertical-tabs.js\"}],\"preloadedCss\":[{\"path\":\"styles\\\/css\\\/vertical-tabs.css\"}],\"preloadedDependencies\":[{\"machineName\":\"FontAwesome\",\"majorVersion\":4,\"minorVersion\":5}]}"]});		H5PIntegration	= (function(x){
			let url	= window.location.href.split('/');
			url.pop();
			x.url	= url.join('/');
			return x;
		})({"baseUrl":"","url":"","siteUrl":"","l10n":{"H5P":{"fullscreen":"Vollbild","disableFullscreen":"Kein Vollbild","download":"Download","copyrights":"Nutzungsrechte","embed":"Einbetten","size":"Size","showAdvanced":"Show advanced","hideAdvanced":"Hide advanced","advancedHelp":"Include this script on your website if you want dynamic sizing of the embedded content:","copyrightInformation":"Nutzungsrechte","close":"Schlie\u00dfen","title":"Titel","author":"Autor","year":"Jahr","source":"Quelle","license":"Lizenz","thumbnail":"Thumbnail","noCopyrights":"Keine Copyright-Informationen vorhanden","reuse":"Wiederverwenden","reuseContent":"Verwende Inhalt","reuseDescription":"Verwende Inhalt.","downloadDescription":"Lade den Inhalt als H5P-Datei herunter.","copyrightsDescription":"Zeige Urheberinformationen an.","embedDescription":"Zeige den Code f\u00fcr die Einbettung an.","h5pDescription":"Visit H5P.org to check out more cool content.","contentChanged":"Dieser Inhalt hat sich seit Ihrer letzten Nutzung ver\u00e4ndert.","startingOver":"Sie beginnen von vorne.","by":"von","showMore":"Zeige mehr","showLess":"Zeige weniger","subLevel":"Sublevel","confirmDialogHeader":"Best\u00e4tige Aktion","confirmDialogBody":"Please confirm that you wish to proceed. This action is not reversible.","cancelLabel":"Abbrechen","confirmLabel":"Best\u00e4tigen","licenseU":"Undisclosed","licenseCCBY":"Attribution","licenseCCBYSA":"Attribution-ShareAlike","licenseCCBYND":"Attribution-NoDerivs","licenseCCBYNC":"Attribution-NonCommercial","licenseCCBYNCSA":"Attribution-NonCommercial-ShareAlike","licenseCCBYNCND":"Attribution-NonCommercial-NoDerivs","licenseCC40":"4.0 International","licenseCC30":"3.0 Unported","licenseCC25":"2.5 Generic","licenseCC20":"2.0 Generic","licenseCC10":"1.0 Generic","licenseGPL":"General Public License","licenseV3":"Version 3","licenseV2":"Version 2","licenseV1":"Version 1","licensePD":"Public Domain","licenseCC010":"CC0 1.0 Universal (CC0 1.0) Public Domain Dedication","licensePDM":"Public Domain Mark","licenseC":"Copyright","contentType":"Inhaltstyp","licenseExtras":"License Extras","changes":"Changelog","contentCopied":"Inhalt wurde ins Clipboard kopiert","connectionLost":"Connection lost. Results will be stored and sent when you regain connection.","connectionReestablished":"Connection reestablished.","resubmitScores":"Attempting to submit stored results.","offlineDialogHeader":"Your connection to the server was lost","offlineDialogBody":"We were unable to send information about your completion of this task. Please check your internet connection.","offlineDialogRetryMessage":"Versuche es wieder in :num....","offlineDialogRetryButtonLabel":"Jetzt nochmal probieren","offlineSuccessfulSubmit":"Erfolgreich Ergebnisse gesendet."}},"hubIsEnabled":false,"reportingIsEnabled":false,"libraryConfig":null,"crossorigin":null,"crossoriginCacheBuster":null,"pluginCacheBuster":"","libraryUrl":".\/libraries\/h5pcore\/js","contents":{"cid-38246_\u0393\u03bb\u03c9\u03c3\u03c3\u03ac\u03c1\u03b9 \u03b3\u03b9\u03b1 \u03c4\u03b7\u03bd \u03bf\u03bc\u03ac\u03b4\u03b1":{"displayOptions":{"copy":false,"copyright":false,"embed":false,"export":false,"frame":false,"icon":false},"embedCode":"","exportUrl":false,"fullScreen":false,"contentUserData":[],"metadata":{"title":"38246_\u0393\u03bb\u03c9\u03c3\u03c3\u03ac\u03c1\u03b9 \u03b3\u03b9\u03b1 \u03c4\u03b7\u03bd \u03bf\u03bc\u03ac\u03b4\u03b1","license":null},"library":"H5P.Dialogcards 1.9","jsonContent":"{\"mode\":\"normal\",\"dialogs\":[{\"text\":\"<p style=\\\"text-align: center;\\\"><strong>\\u03c3\\u03b5\\u03b2\\u03b1\\u03c3\\u03bc\\u03cc\\u03c2<\\\/strong><\\\/p>\\n\",\"answer\":\"<p style=\\\"text-align: center;\\\">\\u03a4\\u03bf \\u03c3\\u03c5\\u03bd\\u03b1\\u03af\\u03c3\\u03b8\\u03b7\\u03bc\\u03b1 \\u03b5\\u03ba\\u03c4\\u03af\\u03bc\\u03b7\\u03c3\\u03b7\\u03c2 \\u03ba\\u03b1\\u03b9 \\u03b8\\u03b1\\u03c5\\u03bc\\u03b1\\u03c3\\u03bc\\u03bf\\u03cd \\u03c0\\u03bf\\u03c5 \\u03bd\\u03b9\\u03ce\\u03b8\\u03bf\\u03c5\\u03bc\\u03b5 \\u03b3\\u03b9\\u03b1 \\u03ba\\u03ac\\u03c0\\u03bf\\u03b9\\u03bf\\u03bd \\u03bf \\u03bf\\u03c0\\u03bf\\u03af\\u03bf\\u03c2 \\u03ad\\u03c7\\u03b5\\u03b9 \\u03b9\\u03b4\\u03b9\\u03b1\\u03af\\u03c4\\u03b5\\u03c1\\u03b7 \\u03b1\\u03be\\u03af\\u03b1 \\u03c9\\u03c2 \\u03b1\\u03bd\\u03b8\\u03c1\\u03c9\\u03c0\\u03bf\\u03c2.<\\\/p>\\n\",\"tips\":{},\"image\":{\"path\":\"images\\\/image-68cbe0bc71510.jpg\",\"mime\":\"image\\\/jpeg\",\"copyright\":{\"license\":\"U\"},\"width\":2343,\"height\":1172},\"audio\":[{\"path\":\"audios\\\/audio-68cbe0c2d30ae.mp3\",\"mime\":\"audio\\\/mpeg\",\"copyright\":{\"license\":\"U\"}}]},{\"text\":\"<p style=\\\"text-align: center;\\\"><strong>\\u03c3\\u03c5\\u03bc\\u03c0\\u03ad\\u03c1\\u03b1\\u03c3\\u03bc\\u03b1<\\\/strong><\\\/p>\\n\",\"answer\":\"<p style=\\\"text-align: center;\\\">\\u0391\\u03c5\\u03c4\\u03cc \\u03c0\\u03bf\\u03c5 \\u03ba\\u03b1\\u03c4\\u03b1\\u03bb\\u03b1\\u03b2\\u03b1\\u03af\\u03bd\\u03bf\\u03c5\\u03bc\\u03b5 \\u03bc\\u03b5\\u03c4\\u03ac \\u03b1\\u03c0\\u03cc \\u03bc\\u03af\\u03b1 \\u03c3\\u03c5\\u03b6\\u03ae\\u03c4\\u03b7\\u03c3\\u03b7 \\u03ae \\u03c4\\u03bf \\u03c4\\u03b5\\u03bb\\u03b9\\u03ba\\u03cc \\u03b1\\u03c0\\u03bf\\u03c4\\u03ad\\u03bb\\u03b5\\u03c3\\u03bc\\u03b1 \\u03bc\\u03b9\\u03b1\\u03c2 \\u03c3\\u03ba\\u03ad\\u03c8\\u03b7\\u03c2.<\\\/p>\\n\",\"tips\":{},\"image\":{\"path\":\"images\\\/image-68cbe11870de7.jpg\",\"mime\":\"image\\\/jpeg\",\"copyright\":{\"license\":\"U\"},\"width\":2343,\"height\":1172},\"audio\":[{\"path\":\"audios\\\/audio-68cbe11e84dba.mp3\",\"mime\":\"audio\\\/mpeg\",\"copyright\":{\"license\":\"U\"}}]},{\"text\":\"<p style=\\\"text-align: center;\\\"><strong>\\u03c6\\u03b9\\u03bb\\u03b1\\u03bd\\u03b8\\u03c1\\u03c9\\u03c0\\u03af\\u03b1<\\\/strong><\\\/p>\\n\",\"answer\":\"<p style=\\\"text-align: center;\\\">\\u0397 \\u03c0\\u03c1\\u03ac\\u03be\\u03b7 \\u03b2\\u03bf\\u03ae\\u03b8\\u03b5\\u03b9\\u03b1\\u03c2 \\u03c0\\u03c1\\u03bf\\u03c2 \\u03c4\\u03bf\\u03c5\\u03c2 \\u03b1\\u03bd\\u03b8\\u03c1\\u03ce\\u03c0\\u03bf\\u03c5\\u03c2 \\u03c0\\u03bf\\u03c5 \\u03ad\\u03c7\\u03bf\\u03c5\\u03bd \\u03b1\\u03bd\\u03ac\\u03b3\\u03ba\\u03b7.<\\\/p>\\n\",\"tips\":{},\"image\":{\"path\":\"images\\\/image-68cbe14cc0225.jpg\",\"mime\":\"image\\\/jpeg\",\"copyright\":{\"license\":\"U\"},\"width\":2343,\"height\":1172},\"audio\":[{\"path\":\"audios\\\/audio-68cbe15414035.mp3\",\"mime\":\"audio\\\/mpeg\",\"copyright\":{\"license\":\"U\"}}]},{\"text\":\"<p style=\\\"text-align: center;\\\"><strong>\\u03c3\\u03c5\\u03bd\\u03b5\\u03c1\\u03b3\\u03b1\\u03c3\\u03af\\u03b1<\\\/strong><\\\/p>\\n\",\"answer\":\"<p style=\\\"text-align: center;\\\">\\u0397 \\u03b1\\u03bd\\u03c4\\u03b1\\u03bb\\u03bb\\u03b1\\u03b3\\u03ae \\u03b2\\u03bf\\u03ae\\u03b8\\u03b5\\u03b9\\u03b1\\u03c2 \\u03ba\\u03b1\\u03b9 \\u03c5\\u03c0\\u03bf\\u03c3\\u03c4\\u03ae\\u03c1\\u03b9\\u03be\\u03b7\\u03c2 \\u03bc\\u03b5\\u03c4\\u03b1\\u03be\\u03cd \\u03c4\\u03c9\\u03bd&nbsp; \\u03b1\\u03c4\\u03cc\\u03bc\\u03c9\\u03bd \\u03bc\\u03b9\\u03b1\\u03c2 \\u03bf\\u03bc\\u03ac\\u03b4\\u03b1\\u03c2.<\\\/p>\\n\",\"tips\":{},\"image\":{\"path\":\"images\\\/image-68cbe1858d3e0.jpg\",\"mime\":\"image\\\/jpeg\",\"copyright\":{\"license\":\"U\"},\"width\":2343,\"height\":1172},\"audio\":[{\"path\":\"audios\\\/audio-68cbe18bbf549.mp3\",\"mime\":\"audio\\\/mpeg\",\"copyright\":{\"license\":\"U\"}}]},{\"text\":\"<p style=\\\"text-align: center;\\\"><strong>\\u03b5\\u03bc\\u03c0\\u03b9\\u03c3\\u03c4\\u03bf\\u03c3\\u03cd\\u03bd\\u03b7<\\\/strong><\\\/p>\\n\",\"answer\":\"<p>\\u03a4\\u03bf \\u03b1\\u03af\\u03c3\\u03b8\\u03b7\\u03bc\\u03b1 \\u03c3\\u03b9\\u03b3\\u03bf\\u03c5\\u03c1\\u03b9\\u03ac\\u03c2 \\u03c0\\u03bf\\u03c5 \\u03bd\\u03b9\\u03ce\\u03b8\\u03bf\\u03c5\\u03bc\\u03b5 \\u03b3\\u03b9\\u03b1 \\u03ba\\u03ac\\u03c0\\u03bf\\u03b9\\u03bf\\u03bd \\u03ba\\u03b1\\u03b9 \\u03b7 \\u03b2\\u03b5\\u03b2\\u03b1\\u03b9\\u03cc\\u03c4\\u03b7\\u03c4\\u03b1 \\u03cc\\u03c4\\u03b9 \\u03b8\\u03b1 \\u03bc\\u03b1\\u03c2 \\u03c3\\u03c4\\u03b7\\u03c1\\u03af\\u03be\\u03b5\\u03b9 \\u03ba\\u03b1\\u03b9 \\u03b8\\u03b1 \\u03bc\\u03b1\\u03c2 \\u03b2\\u03bf\\u03b7\\u03b8\\u03ae\\u03c3\\u03b5\\u03b9.<\\\/p>\\n\",\"tips\":{},\"image\":{\"path\":\"images\\\/image-68cbe1cf626e2.jpg\",\"mime\":\"image\\\/jpeg\",\"copyright\":{\"license\":\"U\"},\"width\":2343,\"height\":1172},\"audio\":[{\"path\":\"audios\\\/audio-68cbe1da20fbc.mp3\",\"mime\":\"audio\\\/mpeg\",\"copyright\":{\"license\":\"U\"}}]}],\"behaviour\":{\"enableRetry\":true,\"disableBackwardsNavigation\":false,\"scaleTextNotCard\":false,\"randomCards\":false,\"maxProficiency\":5,\"quickProgression\":false},\"answer\":\"\\u0393\\u03cd\\u03c1\\u03b9\\u03c3\\u03b5\",\"next\":\"\\u0395\\u03c0\\u03cc\\u03bc\\u03b5\\u03bd\\u03b7\",\"prev\":\"\\u03a0\\u03c1\\u03bf\\u03b7\\u03b3\\u03bf\\u03cd\\u03bc\\u03b5\\u03bd\\u03b7\",\"retry\":\"\\u0395\\u03c0\\u03b1\\u03bd\\u03ac\\u03bb\\u03b7\\u03c8\\u03b7\",\"correctAnswer\":\"\\u03a3\\u03c9\\u03c3\\u03c4\\u03ac!\",\"incorrectAnswer\":\"\\u039b\\u03ac\\u03b8\\u03bf\\u03c2\",\"round\":\"\\u0393\\u03cd\\u03c1\\u03bf\\u03c2 @round\",\"cardsLeft\":\"\\u039a\\u03ac\\u03c1\\u03c4\\u03b5\\u03c2 \\u03c0\\u03bf\\u03c5 \\u03b1\\u03c0\\u03bf\\u03bc\\u03ad\\u03bd\\u03bf\\u03c5\\u03bd: @number\",\"nextRound\":\"\\u039c\\u03b5\\u03c4\\u03ac\\u03b2\\u03b1\\u03c3\\u03b7 \\u03c3\\u03c4\\u03bf \\u03b3\\u03cd\\u03c1\\u03bf @round\",\"startOver\":\"\\u0395\\u03c0\\u03b1\\u03bd\\u03ac\\u03bb\\u03b7\\u03c8\\u03b7\",\"showSummary\":\"\\u0395\\u03c0\\u03b9\\u03c3\\u03ba\\u03cc\\u03c0\\u03b7\\u03c3\\u03b7\",\"summary\":\"\\u0395\\u03c0\\u03b9\\u03c3\\u03ba\\u03cc\\u03c0\\u03b7\\u03c3\\u03b7\",\"summaryCardsRight\":\"\\u039a\\u03ac\\u03c1\\u03c4\\u03b5\\u03c2 \\u03c3\\u03c9\\u03c3\\u03c4\\u03ac:\",\"summaryCardsWrong\":\"\\u039a\\u03ac\\u03c1\\u03c4\\u03b5\\u03c2 \\u03bb\\u03ac\\u03b8\\u03bf\\u03c2:\",\"summaryCardsNotShown\":\"\\u039a\\u03ac\\u03c1\\u03c4\\u03b5\\u03c2 \\u03c0\\u03bf\\u03c5 \\u03b4\\u03b5\\u03bd \\u03c0\\u03c1\\u03bf\\u03b2\\u03bb\\u03ae\\u03b8\\u03b7\\u03ba\\u03b1\\u03bd:\",\"summaryOverallScore\":\"\\u03a3\\u03c5\\u03bd\\u03bf\\u03bb\\u03b9\\u03ba\\u03bf\\u03af \\u0392\\u03b1\\u03b8\\u03bc\\u03bf\\u03af\",\"summaryCardsCompleted\":\"\\u039a\\u03ac\\u03c1\\u03c4\\u03b5\\u03c2 (\\u03bf\\u03bb\\u03bf\\u03ba\\u03bb\\u03b7\\u03c1\\u03ce\\u03b8\\u03b7\\u03ba\\u03b5 \\u03b7 \\u03bc\\u03ac\\u03b8\\u03b7\\u03c3\\u03ae \\u03c4\\u03bf\\u03c5\\u03c2):\",\"summaryCompletedRounds\":\"\\u0393\\u03cd\\u03c1\\u03bf\\u03b9 \\u03c0\\u03bf\\u03c5 \\u03bf\\u03bb\\u03bf\\u03ba\\u03bb\\u03b7\\u03c1\\u03ce\\u03b8\\u03b7\\u03ba\\u03b1\\u03bd:\",\"summaryAllDone\":\"\\u03a3\\u03c5\\u03b3\\u03c7\\u03b1\\u03c1\\u03b7\\u03c4\\u03ae\\u03c1\\u03b9\\u03b1! \\u0395\\u03af\\u03c7\\u03b5\\u03c2 \\u03cc\\u03bb\\u03b5\\u03c2 \\u03c4\\u03b9\\u03c2 \\u03ba\\u03ac\\u03c1\\u03c4\\u03b5\\u03c2 (@cards) \\u03c3\\u03c9\\u03c3\\u03c4\\u03ac @max \\u03c6\\u03bf\\u03c1\\u03ad\\u03c2 \\u03c3\\u03c4\\u03b7 \\u03c3\\u03b5\\u03b9\\u03c1\\u03ac!\",\"progressText\":\"\\u039a\\u03ac\\u03c1\\u03c4\\u03b1 @card \\u03b1\\u03c0\\u03cc @total\",\"cardFrontLabel\":\"\\u039c\\u03c0\\u03c1\\u03bf\\u03c3\\u03c4\\u03b9\\u03bd\\u03cc \\u03bc\\u03ad\\u03c1\\u03bf\\u03c2 \\u03ba\\u03ac\\u03c1\\u03c4\\u03b1\\u03c2\",\"cardBackLabel\":\"\\u03a0\\u03af\\u03c3\\u03c9 \\u03bc\\u03ad\\u03c1\\u03bf\\u03c2 \\u03ba\\u03ac\\u03c1\\u03c4\\u03b1\\u03c2\",\"tipButtonLabel\":\"\\u0395\\u03bc\\u03c6\\u03ac\\u03bd\\u03b9\\u03c3\\u03b7 \\u03b5\\u03c0\\u03b5\\u03be\\u03ae\\u03b3\\u03b7\\u03c3\\u03b7\\u03c2\",\"audioNotSupported\":\"\\u039f \\u03c6\\u03c5\\u03bb\\u03bb\\u03bf\\u03bc\\u03b5\\u03c4\\u03c1\\u03b7\\u03c4\\u03ae\\u03c2 \\u03b4\\u03b5\\u03bd \\u03c5\\u03c0\\u03bf\\u03c3\\u03c4\\u03b7\\u03c1\\u03af\\u03b6\\u03b5\\u03b9 \\u03c4\\u03bf \\u03c3\\u03c5\\u03b3\\u03ba\\u03b5\\u03ba\\u03c1\\u03b9\\u03bc\\u03ad\\u03bd\\u03bf \\u03b1\\u03c1\\u03c7\\u03b5\\u03af\\u03bf \\u03ae\\u03c7\\u03bf\\u03c5\",\"confirmStartingOver\":{\"header\":\"\\u0395\\u03c0\\u03b1\\u03bd\\u03ad\\u03bd\\u03b1\\u03c1\\u03be\\u03b7;\",\"body\":\"\\u038c\\u03bb\\u03b7 \\u03b7 \\u03c4\\u03c1\\u03ad\\u03c7\\u03bf\\u03c5\\u03c3\\u03b1 \\u03c0\\u03c1\\u03cc\\u03bf\\u03b4\\u03bf\\u03c2 \\u03b8\\u03b1 \\u03c7\\u03b1\\u03b8\\u03b5\\u03af. \\u0395\\u03af\\u03c3\\u03c4\\u03b5 \\u03c3\\u03af\\u03b3\\u03bf\\u03c5\\u03c1\\u03bf\\u03c2\\\/\\u03b7 \\u03c0\\u03c9\\u03c2 \\u03b8\\u03ad\\u03bb\\u03b5\\u03c4\\u03b5 \\u03bd\\u03b1 \\u03be\\u03b5\\u03ba\\u03b9\\u03bd\\u03ae\\u03c3\\u03b5\\u03c4\\u03b5 \\u03be\\u03b1\\u03bd\\u03ac;\",\"cancelLabel\":\"\\u0391\\u03ba\\u03cd\\u03c1\\u03c9\\u03c3\\u03b7\",\"confirmLabel\":\"\\u0395\\u03c0\\u03b1\\u03bd\\u03ad\\u03bd\\u03b1\\u03c1\\u03be\\u03b7\"},\"title\":\"<p style=\\\"text-align: center;\\\">\\u0388\\u03bd\\u03b1 \\u03b3\\u03bb\\u03c9\\u03c3\\u03c3\\u03ac\\u03c1\\u03b9 \\u03b3\\u03b9\\u03b1 \\u03c4\\u03b7\\u03bd \\u03bf\\u03bc\\u03ac\\u03b4\\u03b1<\\\/p>\\n\",\"description\":\"<p style=\\\"text-align: center;\\\">\\u039c\\u03b1\\u03b8\\u03b1\\u03af\\u03bd\\u03c9 \\u03c4\\u03b7 \\u03c3\\u03b7\\u03bc\\u03b1\\u03c3\\u03af\\u03b1 \\u03c4\\u03c9\\u03bd \\u03bb\\u03ad\\u03be\\u03b5\\u03c9\\u03bd \\u03ba\\u03b1\\u03b9 \\u03b1\\u03ba\\u03bf\\u03cd\\u03c9 \\u03c0\\u03ce\\u03c2 \\u03bc\\u03c0\\u03bf\\u03c1\\u03bf\\u03cd\\u03bd \\u03bd\\u03b1 \\u03c7\\u03c1\\u03b7\\u03c3\\u03b9\\u03bc\\u03bf\\u03c0\\u03bf\\u03b9\\u03b7\\u03b8\\u03bf\\u03cd\\u03bd \\u03bc\\u03ad\\u03c3\\u03b1 \\u03c3\\u03b5 \\u03bc\\u03af\\u03b1 \\u03c0\\u03c1\\u03cc\\u03c4\\u03b1\\u03c3\\u03b7:<\\\/p>\\n\"}"}}});