UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

145 lines (144 loc) 6.35 kB
function _class_call_check(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for(var i = 0; i < props.length; i++){ var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _create_class(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _define_property(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } import sortBy from 'lodash/sortBy'; import setFromArray from '../../../../util/setFromArray'; var EditStemController = /*#__PURE__*/ function() { "use strict"; function EditStemController(props) { var _this = this; _class_call_check(this, EditStemController); _define_property(this, "UNSAFE_componentWillReceiveProps", function(props) { _this.props = props; }); _define_property(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; }); _define_property(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; } _create_class(EditStemController, [ { // =========== // ACTIONS // =========== key: "insertTextAtCursor", value: 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 (e) { // 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; } } }, { // 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. key: "getFocusData", value: 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 }; } } ]); return EditStemController; }(); export { EditStemController as default };