UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

109 lines (108 loc) 4.42 kB
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck"; import _createClass from "@babel/runtime/helpers/esm/createClass"; import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import sortBy from 'lodash/sortBy'; import setFromArray from '../../../../util/setFromArray'; var EditStemController = /*#__PURE__*/function () { function EditStemController(_props) { var _this = this; _classCallCheck(this, EditStemController); _defineProperty(this, "UNSAFE_componentWillReceiveProps", function (props) { _this.props = props; }); _defineProperty(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; }); _defineProperty(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 _createClass(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 = setFromArray(prevProps.stemItems.map(function (item) { return item.id; })); var currIds = setFromArray(this.props.stemItems.map(function (item) { return item.id; })); var newItems = this.props.stemItems.filter(function (item) { return !prevIds.has(item.id); }); var deletedItems = sortBy(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 = sortBy(this.props.stemItems, ['position']); var modifiedItem = sortedItems[deletedItems[0].position - 1]; return { stemItem: modifiedItem || sortedItems[0], cursorPosition: modifiedItem.value.length - lastDeletedItem.value.length }; } }]); }(); export { EditStemController as default };