@oat-sa/tao-test-runner-qti
Version:
TAO Test Runner QTI implementation
135 lines (126 loc) • 6.83 kB
JavaScript
define(['jquery', 'util/typeCaster', 'taoTests/runner/plugin', 'taoQtiTest/runner/helpers/verticalWriting'], function ($, typeCaster, pluginFactory, verticalWriting) { 'use strict';
$ = $ && Object.prototype.hasOwnProperty.call($, 'default') ? $['default'] : $;
typeCaster = typeCaster && Object.prototype.hasOwnProperty.call(typeCaster, 'default') ? typeCaster['default'] : typeCaster;
pluginFactory = pluginFactory && Object.prototype.hasOwnProperty.call(pluginFactory, 'default') ? pluginFactory['default'] : pluginFactory;
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2020 (original work) Open Assessment Technologies SA;
*/
/**
* Creates the loading bar plugin.
* Displays a loading bar when a blocking task is running
*/
var itemScrolling = pluginFactory({
name: 'itemScrolling',
/**
* Initializes the plugin (called during runner's init)
*/
init: function init() {
const testRunner = this.getTestRunner();
const $contentArea = testRunner.getAreaBroker().getContentArea();
testRunner.on('renderitem', function () {
const isVerticalWritingMode = verticalWriting.getIsItemWritingModeVerticalRl();
if (isVerticalWritingMode) {
// qti-itemBody is item scroll container in vertical writing mode (but not in horizontal);
// window resize is not enough, because if review-panel is used, it can be closed/opened, and that affects qti-itemBody width.
const $itemBody = $('.qti-itemBody');
this.itemBodyResizeObserver = new ResizeObserver(() => requestAnimationFrame(adaptItemBlockSize));
this.itemBodyResizeObserver.observe($itemBody.get(0));
} else {
adaptItemBlockSize();
$(window).on('resize.adaptItemHeight', adaptItemBlockSize);
}
}).on('unloaditem', function () {
$(window).off('resize.adaptItemHeight');
if (this.itemBodyResizeObserver) {
this.itemBodyResizeObserver.disconnect();
}
});
function adaptItemBlockSize() {
const isVerticalWritingMode = verticalWriting.getIsItemWritingModeVerticalRl();
const gridRowBlockEndMargin = 12;
const qtiItemPadding = (isVerticalWritingMode ? 15 : 30) * 2;
const $itemContainer = $contentArea.find('[data-scrolling="true"]');
const contentBlockSize = getItemRunnerBlockSize(isVerticalWritingMode) - getExtraGridRowBlockSize(isVerticalWritingMode) - getSpaceAroundQtiContent(isVerticalWritingMode) - gridRowBlockEndMargin - qtiItemPadding - 2;
$itemContainer.each(function () {
const $item = $(this);
const isScrollable = typeCaster.strToBool($item.attr('data-scrolling') || 'false');
const selectedBlockSize = parseFloat($item.attr('data-scrolling-height')) || 100;
const containerParent = $item.parent().closest('[data-scrolling="true"]');
const containerBlockSize = isVerticalWritingMode ? containerParent.width() : containerParent.height();
const overflowCssProp = isVerticalWritingMode ? 'overflow-x' : 'overflow-y';
if ($item.length && isScrollable) {
$item.data('scrollable', true);
$item.css({
[overflowCssProp]: 'scroll'
});
if (containerParent.length > 0) {
$item.css('max-block-size', `${containerBlockSize * (selectedBlockSize * 0.01)}px`);
} else {
$item.css('max-block-size', `${contentBlockSize * (selectedBlockSize * 0.01)}px`);
}
}
});
}
// depending on the context (item preview, new/old test runner...) available height is computed differently
function getItemRunnerBlockSize(isVerticalWritingMode) {
var $testRunnerSections = $('.test-runner-sections');
// exists only in the new test runner
if ($testRunnerSections.length) {
const rect = $testRunnerSections.get(0).getBoundingClientRect();
return isVerticalWritingMode ? rect.width : rect.height;
}
// otherwise, we assume that we are in an iframe with all space available (= item preview, old test runner)
return isVerticalWritingMode ? $(window).width() : $(window).height();
}
// extra grid row are there in case of a vertical layout (item on top/bottom of the question)
function getExtraGridRowBlockSize(isVerticalWritingMode) {
var $gridRows = $('.qti-itemBody > .grid-row'),
extraBlockSize = 0;
$gridRows.each(function () {
var $gridRow = $(this),
$itemContainer = $gridRow.find('[data-scrolling="true"]');
if (!$itemContainer.length) {
extraBlockSize += isVerticalWritingMode ? $gridRow.outerWidth(true) : $gridRow.outerHeight(true);
}
});
return extraBlockSize;
}
// most of the time this will be rubrick's block height in the new test runner;
// if vertical-writing, can also be review-panel on the left
function getSpaceAroundQtiContent(isVerticalWritingMode) {
var $testRunnerSections = $('.test-runner-sections'),
$qtiContent = $('#qti-content');
if ($testRunnerSections.length && $qtiContent.length) {
const qtiContentRect = $qtiContent.get(0).getBoundingClientRect();
const testRunnerSectionsRect = $testRunnerSections.get(0).getBoundingClientRect();
if (isVerticalWritingMode) {
return testRunnerSectionsRect.width - qtiContentRect.width;
}
return qtiContentRect.top - testRunnerSectionsRect.top;
}
return 0;
}
},
destroy: function destroy() {
$(window).off('resize.adaptItemHeight');
if (this.itemBodyResizeObserver) {
this.itemBodyResizeObserver.disconnect();
}
}
});
return itemScrolling;
});