@instructure/quiz-interactions
Version:
A React UI component Library for quiz interaction types.
115 lines (113 loc) • 4.88 kB
JavaScript
;
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
};
}
}]);
}();