UNPKG

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

Version:
212 lines (198 loc) 7.27 kB
define(['lodash', 'jquery', 'core/eventifier', 'ui/highlighter'], function (_, $, eventifier, highlighterFactory) { 'use strict'; _ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _; $ = $ && Object.prototype.hasOwnProperty.call($, 'default') ? $['default'] : $; eventifier = eventifier && Object.prototype.hasOwnProperty.call(eventifier, 'default') ? eventifier['default'] : eventifier; highlighterFactory = highlighterFactory && Object.prototype.hasOwnProperty.call(highlighterFactory, 'default') ? highlighterFactory['default'] : highlighterFactory; /** * 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; */ var prevSelection = []; var selection; if (!window.getSelection) throw new Error('Browser does not support getSelection()'); selection = window.getSelection(); /** * Returns an array of active ranges. * If browser doesn't support multiple Ranges, returns only the first range * see note on https://w3c.github.io/selection-api/#methods * * @returns {Range[]} */ function getAllRanges() { var i, allRanges = []; for (i = 0; i < selection.rangeCount; i++) { allRanges.push(selection.getRangeAt(i)); } return allRanges; } /** * Discards the global text selection from the browser (window.selection) */ function discardSelection() { // delay discarding, to allow time for multiple highlighters logic setTimeout(function () { selection.removeAllRanges(); }, 250); } /** * The highlighter Factory * @param {Object} options * @param {String} [options.className] * @param {String} [options.containerSelector] * @param {Array} [options.containersBlackList] * @param {String} [options.id] * @returns {Object} the highlighter instance */ function testHighlighterFactory(options) { /** * Is this highlighter enabled or disabled? * @type {boolean} */ var enabled = true; /** * Are we in highlight mode, meaning that each new selection is automatically highlighted * without having to press any button * @type {boolean} */ var isHighlighting = false; /** * The helper that does the highlight magic */ var highlightHelper = highlighterFactory({ className: options.className || 'txt-user-highlight', containerSelector: options.containerSelector || '.qti-itemBody', containersBlackList: options.containersBlackList || [], clearOnClick: true }); //add event to automatically highlight the recently made selection if needed $(document).on('mouseup.highlighter', function () { if (isHighlighting && !selection.isCollapsed) { highlightHelper.highlightRanges(getAllRanges()); discardSelection(); } }); //add event to automatically highlight the recently made selection if needed //added touch event (as from TAO-6578) $(document).on('touchend.highlighter', function () { if (isHighlighting && !selection.isCollapsed) { highlightHelper.highlightRanges(getAllRanges()); } }); // iOS devices clears selection after click on button, // so we store prev selection for this devices to be able // to use it after click on highlight button if (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) { $(document).on('selectionchange', function () { if (!isHighlighting) { prevSelection = _.clone(getAllRanges(), true); } }); } /** * The highlighter instance */ return eventifier({ /** * Enable this instance */ enable: function enable() { enabled = true; }, /** * Disable this instance */ disable: function disable() { enabled = false; }, /** * Is this instance currently enabled? * @returns {Boolean} */ isEnabled: function isEnabled() { return enabled; }, /** * toggle highlighting mode on and off * @param {Boolean} bool - wanted state */ toggleHighlighting: function toggleHighlighting(bool) { isHighlighting = bool; if (isHighlighting) { this.trigger('start'); $('.qti-itemBody').toggleClass('highlighter-cursor', true); } else { this.trigger('end'); $('.qti-itemBody').toggleClass('highlighter-cursor', false); } return this; }, /** * Either highlight the current or selection, or toggle highlighting mode */ highlight: function highlight() { if (!isHighlighting) { if (!selection.isCollapsed) { this.toggleHighlighting(true); highlightHelper.highlightRanges(getAllRanges()); this.toggleHighlighting(false); discardSelection(); } else if (prevSelection[0] && !prevSelection[0].collapsed) { this.toggleHighlighting(true); highlightHelper.highlightRanges(prevSelection); this.toggleHighlighting(false); discardSelection(); } else { this.toggleHighlighting(true); } } else { this.toggleHighlighting(false); } }, /** * restore the highlight from a given index * @param {Array} index */ restoreIndex: function restoreIndex(index) { if (index && index.length > 0) { highlightHelper.highlightFromIndex(index); } }, /** * Get the current index * @returns {Array} index */ getIndex: function getIndex() { return highlightHelper.getHighlightIndex(); }, /** * remove all highlights */ clearHighlights: function clearHighlights() { highlightHelper.clearHighlights(); selection.removeAllRanges(); }, /** * Getter for the instance's id * @returns {String} */ getId: function getId() { return options.id; } }); } return testHighlighterFactory; });