UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

115 lines (113 loc) 4.88 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _sortBy = _interopRequireDefault(require("lodash/sortBy")); var _setFromArray = _interopRequireDefault(require("../../../../util/setFromArray")); var EditStemController = exports["default"] = /*#__PURE__*/function () { function EditStemController(_props) { var _this = this; (0, _classCallCheck2["default"])(this, EditStemController); (0, _defineProperty2["default"])(this, "UNSAFE_componentWillReceiveProps", function (props) { _this.props = props; }); (0, _defineProperty2["default"])(this, "textForStemItem", function (stemItem) { if (stemItem.type !== 'blank') { return stemItem.value; } var matchingData = _this.props.scoringData.value.find(function (sd) { return sd.id === stemItem.blankId; }); return matchingData.scoringData.blankText; }); (0, _defineProperty2["default"])(this, "handlePaste", function (e) { e.stopPropagation(); e.preventDefault(); var clipboardData = e.clipboardData || window.clipboardData; var pastedData = clipboardData.getData('Text'); _this.insertTextAtCursor(pastedData, e); }); this.props = _props; } return (0, _createClass2["default"])(EditStemController, [{ key: "insertTextAtCursor", value: // =========== // ACTIONS // =========== function insertTextAtCursor(text, e) { if (window.getSelection) { var sel = window.getSelection(); if (sel.getRangeAt && sel.rangeCount) { var range = sel.getRangeAt(0); range.deleteContents(); var newNode = document.createTextNode(text); range.insertNode(newNode); // This merges adjacent text nodes, as we just inserted a new one. // Necessary to prevent weird selection errors from happening on some // browsers, since they'll otherwise disagree on where the selection begins. e.target.normalize(); var newRange = sel.getRangeAt(0); // We want to extend the selection to a text node rather than an element // to prevent more browser compatibility issues. var newContainer = newRange.startContainer.nodeType === Node.ELEMENT_NODE ? newRange.startContainer.childNodes[0] : newRange.startContainer; try { sel.extend(newContainer, newRange.startOffset + text.length); } catch (_unused) { // Safari errors out inexplicably on above line, so this is a workaround. // All other methods I tried fail on at least one other browser. newRange.setEnd(newContainer, newRange.endOffset + text.length); sel.addRange(newRange); } sel.collapseToEnd(); } } else if (document.selection && document.selection.createRange) { document.selection.createRange().text = text; } } }, { key: "getFocusData", value: // If a new blank was added, we should focus on it. If a blank was deleted, // we need to focus on the textual stem item that the blank's text was merged // into, and report the correct cursor position to focus on. function getFocusData(prevProps) { var prevIds = (0, _setFromArray["default"])(prevProps.stemItems.map(function (item) { return item.id; })); var currIds = (0, _setFromArray["default"])(this.props.stemItems.map(function (item) { return item.id; })); var newItems = this.props.stemItems.filter(function (item) { return !prevIds.has(item.id); }); var deletedItems = (0, _sortBy["default"])(prevProps.stemItems.filter(function (item) { return !currIds.has(item.id); }), ['position']); if (newItems.length === 0 && deletedItems.length === 0) { return null; } var newBlank = newItems.find(function (item) { return item.type === 'blank'; }); if (newBlank) { return { stemItem: newBlank, cursorPosition: null }; } var lastDeletedItem = deletedItems[deletedItems.length - 1]; var sortedItems = (0, _sortBy["default"])(this.props.stemItems, ['position']); var modifiedItem = sortedItems[deletedItems[0].position - 1]; return { stemItem: modifiedItem || sortedItems[0], cursorPosition: modifiedItem.value.length - lastDeletedItem.value.length }; } }]); }();