UNPKG

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

Version:
229 lines (209 loc) 9.12 kB
define(['jquery', 'lodash', 'taoTests/runner/plugin', 'ui/dialog/alert', 'ui/dialog/confirm', 'util/shortcut/registry', 'util/shortcut', 'util/namespace'], function ($, _, pluginFactory, dialogAlert, dialogConfirm, shortcutRegistry, globalShortcut, namespaceHelper) { 'use strict'; $ = $ && Object.prototype.hasOwnProperty.call($, 'default') ? $['default'] : $; _ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _; pluginFactory = pluginFactory && Object.prototype.hasOwnProperty.call(pluginFactory, 'default') ? pluginFactory['default'] : pluginFactory; dialogAlert = dialogAlert && Object.prototype.hasOwnProperty.call(dialogAlert, 'default') ? dialogAlert['default'] : dialogAlert; dialogConfirm = dialogConfirm && Object.prototype.hasOwnProperty.call(dialogConfirm, 'default') ? dialogConfirm['default'] : dialogConfirm; shortcutRegistry = shortcutRegistry && Object.prototype.hasOwnProperty.call(shortcutRegistry, 'default') ? shortcutRegistry['default'] : shortcutRegistry; globalShortcut = globalShortcut && Object.prototype.hasOwnProperty.call(globalShortcut, 'default') ? globalShortcut['default'] : globalShortcut; namespaceHelper = namespaceHelper && Object.prototype.hasOwnProperty.call(namespaceHelper, 'default') ? namespaceHelper['default'] : namespaceHelper; /** * 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) 2016 (original work) Open Assessment Technologies SA ; */ /** * The public name of the plugin * @type {String} */ var pluginName = 'dialog'; /** * The prefix of actions triggered through the event loop * @type {String} */ var actionPrefix = `tool-${pluginName}-`; /** * Some default options for the plugin * @type {Object} */ var defaultOptions = { alert: { focus: 'ok' }, confirm: { focus: 'ok' } }; /** * Returns the configured plugin */ var dialog = pluginFactory({ name: pluginName, /** * Initialize the plugin (called during runner's init) */ init: function init() { var testRunner = this.getTestRunner(); var testOptions = testRunner.getOptions(); var pluginConfig = Object.assign({}, defaultOptions, this.getConfig()); var pluginShortcuts = (testOptions.shortcuts || {})[pluginName] || {}; var alerts = []; var confirms = []; var opened = []; var dialogShortcut = shortcutRegistry($('body'), { propagate: false, prevent: true }); /** * Closes a dialog with accept * @param {dialog} dialog - The instance of the dialog */ function closeAccept(dialog) { // TODO: improve the dialog implementation in order to provide a better API dialog.trigger('okbtn.modal').hide(); } /** * Closes a dialog with rejection * @param {dialog} dialog - The instance of the dialog */ function closeReject(dialog) { dialog.hide(); } /** * Closes the last opened dialog * @param {Boolean} accept Whether the dialog should be accepted or not * @param {String} [shortcut] The shortcut that caused the action */ function closeLast(accept, shortcut) { var handle = opened.length && opened[opened.length - 1]; if (handle) { handle.shortcut = shortcut; if (accept) { closeAccept(handle.dialog); } else { closeReject(handle.dialog); } } } /** * Add dialog on top of the provided stack * @param {String} namespace - The event namespace that scope the dialog * @param {Array} stack - The dialogs stack on which push the new instance * @param {Function} dialog - The constructor of the dialog * @param {String} message - The message to display * @param {Function} accept - The callback for accept * @param {Function} reject - The callback for reject * @param {Object} options - Dialog options */ function addHandle(namespace, stack, dialog, message, accept, reject, options) { var handle = { context: namespace, dialog: dialog(message, doAccept, doReject, options) }; function doAccept(e, reason) { if (_.isFunction(accept)) { accept(handle.shortcut || reason); } } function doReject(e, reason) { if (_.isFunction(reject)) { reject(handle.shortcut || reason); } } // prevents all registered shortcuts to be triggered // and brings back the dialog shortcuts globalShortcut.disable(); dialogShortcut.enable(); stack.push(handle); opened.push(handle); handle.dialog.focus(options.focus); handle.dialog.on('closed.modal', function () { removeHandle(stack, handle.dialog); removeHandle(opened, handle.dialog); // if all dialogs have been closed allows all registered shortcuts to be triggered // also disables the dialog shortcuts if (!opened.length) { globalShortcut.enable(); dialogShortcut.disable(); } }); } /** * Remove a dialog from the provided stack * @param {Array} stack - The dialogs stack from which remove the dialog instance * @param {dialog} dialog - The instance of the dialog */ function removeHandle(stack, dialog) { if (dialog) { _.remove(stack, function (handle) { if (handle && dialog === handle.dialog) { return true; } }); } } /** * Closes all dialogs within the provided stack * @param {String} namespace - The event namespace that scope the dialogs to close * @param {Boolean} accept - Whether (`true`) or not (`false`) to close the dialogs with accept * @param {Array} stack - The dialogs stack in which close the dialogs */ function closeDialogs(namespace, accept, stack) { if (stack) { _.forEach(stack, function (handle) { if (handle && (namespace === '@' || namespace === handle.context)) { if (accept) { closeAccept(handle.dialog); } else { closeReject(handle.dialog); } } }); } else { closeDialogs(namespace, accept, alerts); closeDialogs(namespace, accept, confirms); } } // starts with shortcuts disabled, prevents the TAB key to be used to move outside the dialog box dialogShortcut.disable().set('Tab Shift+Tab'); // handle the plugin's shortcuts if (testOptions.allowShortcuts) { _.forEach(pluginShortcuts, function (command, key) { dialogShortcut.add(namespaceHelper.namespaceAll(command, pluginName, true), function (e, shortcut) { // just fire the action using the event loop testRunner.trigger(actionPrefix + key, shortcut); }); }); } //change plugin state testRunner.before('alert.*', function (e, msg, accept, options) { addHandle(e.namespace, alerts, dialogAlert, msg, accept, accept, _.merge({}, pluginConfig.alert, options)); }).before('confirm.*', function (e, msg, accept, reject, options) { addHandle(e.namespace, confirms, dialogConfirm, msg, accept, reject, _.merge({}, pluginConfig.confirm, options)); }).before('closedialog.*', function (e, accept) { closeDialogs(e.namespace, accept); }).on(`${actionPrefix}accept`, function (shortcut) { closeLast(true, shortcut); }).on(`${actionPrefix}reject`, function (shortcut) { closeLast(false, shortcut); }).on('destroy', function () { closeDialogs('.@'); dialogShortcut.clear(); dialogShortcut = null; }); } }); return dialog; });