UNPKG

@oat-sa/tao-test-runner-qti

Version:
177 lines (168 loc) 8.65 kB
define(['i18n', 'jquery', 'taoTests/runner/plugin', 'taoQtiTest/runner/helpers/isReviewPanelEnabled', 'taoQtiTest/runner/plugins/content/accessibility/jumplinks/helpers', 'taoQtiTest/runner/plugins/content/accessibility/jumplinks/jumplinks', 'taoQtiTest/runner/plugins/content/accessibility/jumplinks/shortcuts', 'util/shortcut', 'util/namespace', 'handlebars', 'lib/handlebars/helpers'], function (__, $$1, pluginFactory, isReviewPanelEnabled, helpers, jumplinksFactory, shortcutsFactory, shortcut, namespaceHelper, Handlebars, Helpers0) { 'use strict'; __ = __ && Object.prototype.hasOwnProperty.call(__, 'default') ? __['default'] : __; $$1 = $$1 && Object.prototype.hasOwnProperty.call($$1, 'default') ? $$1['default'] : $$1; pluginFactory = pluginFactory && Object.prototype.hasOwnProperty.call(pluginFactory, 'default') ? pluginFactory['default'] : pluginFactory; isReviewPanelEnabled = isReviewPanelEnabled && Object.prototype.hasOwnProperty.call(isReviewPanelEnabled, 'default') ? isReviewPanelEnabled['default'] : isReviewPanelEnabled; jumplinksFactory = jumplinksFactory && Object.prototype.hasOwnProperty.call(jumplinksFactory, 'default') ? jumplinksFactory['default'] : jumplinksFactory; shortcutsFactory = shortcutsFactory && Object.prototype.hasOwnProperty.call(shortcutsFactory, 'default') ? shortcutsFactory['default'] : shortcutsFactory; shortcut = shortcut && Object.prototype.hasOwnProperty.call(shortcut, 'default') ? shortcut['default'] : shortcut; namespaceHelper = namespaceHelper && Object.prototype.hasOwnProperty.call(namespaceHelper, 'default') ? namespaceHelper['default'] : namespaceHelper; Handlebars = Handlebars && Object.prototype.hasOwnProperty.call(Handlebars, 'default') ? Handlebars['default'] : Handlebars; Helpers0 = Helpers0 && Object.prototype.hasOwnProperty.call(Helpers0, 'default') ? Helpers0['default'] : Helpers0; if (!Helpers0.__initialized) { Helpers0(Handlebars); Helpers0.__initialized = true; } var Template = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) { this.compilerInfo = [4,'>= 1.0.0']; helpers = this.merge(helpers, Handlebars.helpers); return "<div class=\"jump-links-container\"></div>\n"; }); function containerTpl(data, options, asString) { var html = Template(data, options); return (asString || true) ? html : $(html); } /** * 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 JumpLinks plugin. * adding jumplinks accessibility feature for quick navigation */ var plugin = pluginFactory({ name: 'jumplinks', /** * Initializes the plugin (called during runner's init) */ init() { const testRunner = this.getTestRunner(); const item = testRunner.getCurrentItem(); const config = { isReviewPanelEnabled: isReviewPanelEnabled(testRunner), questionStatus: helpers.getItemStatus(item) }; const testRunnerOptions = testRunner.getOptions(); const pluginShortcuts = (testRunnerOptions.shortcuts || {})[this.getName()] || {}; const areaBroker = this.getAreaBroker(); const getJumpElement = helpers.getJumpElementFactory(areaBroker); const shortcutsConfig = navigator.appVersion.indexOf("Mac") !== -1 ? { shortcutsGroups: [{ id: 'navigation-shortcuts', label: __('Navigation shortcuts'), shortcuts: [{ id: 'next', shortcut: 'OPTION + Shift + N', label: __('Go to the next question') }, { id: 'previous', shortcut: 'OPTION + Shift + P', label: __('Go to the previous question') }, { id: 'current', shortcut: 'OPTION + Shift + Q', label: __('Go to the current question') }, { id: 'top', shortcut: 'OPTION + Shift + T', label: __('Go to the top of the page') }] }] } : {}; if (testRunnerOptions.allowShortcuts) { pluginShortcuts.goToTop && shortcut.add(namespaceHelper.namespaceAll(pluginShortcuts.goToTop, this.getName(), true), function () { $$1('[tabindex]').first().focus(); }, { avoidInput: true, prevent: true }); pluginShortcuts.goToQuestion && shortcut.add(namespaceHelper.namespaceAll(pluginShortcuts.goToQuestion, this.getName(), true), function () { getJumpElement.question.focus(); }, { avoidInput: true, prevent: true }); } this.jumplinks = jumplinksFactory(config).on('render', () => { this.jumplinks.on('jump', jumpTo => { const $element = getJumpElement[jumpTo]; $element.focus(); }); this.jumplinks.on('shortcuts', () => { if (this.shortcuts) { return; } this.shortcuts = shortcutsFactory(shortcutsConfig); this.shortcuts.render(this.getAreaBroker().getControlArea()); this.shortcuts.on('close', () => { this.shortcuts.destroy(); this.shortcuts = null; }); }); }).on('update', function update(params) { this.trigger('changeReviewPanel', params.isReviewPanelEnabled); this.trigger('changeQuesitionStatus', params.questionStatus); }).on('changeReviewPanel', function changeReviewPanel(enabled) { const elem = this.getElement(); const panelJumplink = elem.find('[data-jump="teststatus"]').parent(); if (enabled) { panelJumplink.removeClass('hidden'); } else { panelJumplink.addClass('hidden'); } }).on('changeQuesitionStatus', function changeQuesitionStatus(questionStatus) { const elem = this.getElement(); const text = `${__('Question')} - ${questionStatus}`; elem.find('[data-jump="question"] > b').text(text); }); testRunner.on('renderitem', () => { const currentItem = testRunner.getCurrentItem(); const updatedConfig = { isReviewPanelEnabled: !helpers.isReviewPanelHidden(testRunner) && isReviewPanelEnabled(testRunner), questionStatus: helpers.getItemStatus(currentItem) }; const announcedText = __('Item %s loaded', currentItem.position); let $announce = $$1('[aria-live=polite][role=alert]').first(); if ($announce.length !== 1) { $announce = $$1('<div aria-live="polite" role="alert" class="visible-hidden"></div>'); $$1('main').first().append($announce); } $announce.text(announcedText); this.jumplinks.trigger('update', updatedConfig); }).on('tool-flagitem', () => { const currentItem = testRunner.getCurrentItem(); const questionStatus = helpers.getItemStatus(Object.assign({}, currentItem, { flagged: !currentItem.flagged })); this.jumplinks.trigger('changeQuesitionStatus', questionStatus); }).on('tool-reviewpanel', () => { const wasHidden = helpers.isReviewPanelHidden(testRunner); this.jumplinks.trigger('changeReviewPanel', wasHidden); }).after('renderitem', () => { getJumpElement.question.attr('tabindex', '-1').focus(); }); }, /** * Called during the runner's render phase */ render: function render() { const jumplinksContainer = $$1(containerTpl()); $$1('.content-wrap').prepend(jumplinksContainer); this.jumplinks.render(jumplinksContainer); } }); return plugin; });