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