/* * Copyright (c) 2023 ETH Zürich, Educational Development and Technology (LET) * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Original code taken and slightly adapted from https://github.com/eqsoft/seb2/blob/master/browser/app/modules/SebBrowser.jsm#L1215. */ SafeExamBrowser.clipboard = { clear: function () { ranges = []; text = ""; }, ranges: [], text: "" } function copySelectedData(e) { if (e.target.contentEditable && e.target.setRangeText) { SafeExamBrowser.clipboard.text = e.target.value.substring(e.target.selectionStart, e.target.selectionEnd); SafeExamBrowser.clipboard.ranges = []; } else { var selection = e.target.ownerDocument.defaultView.getSelection(); var text = ""; for (var i = 0; i < selection.rangeCount; i++) { SafeExamBrowser.clipboard.ranges[i] = selection.getRangeAt(i).cloneContents(); text += SafeExamBrowser.clipboard.ranges[i].textContent; } SafeExamBrowser.clipboard.text = text; } } function cutSelectedData(e) { if (e.target.contentEditable && e.target.setRangeText) { e.target.setRangeText("", e.target.selectionStart, e.target.selectionEnd, 'select'); } else { var designMode = e.target.ownerDocument.designMode; var contentEditables = e.target.ownerDocument.querySelectorAll('*[contenteditable]'); var selection = e.target.ownerDocument.defaultView.getSelection(); for (var i = 0; i < selection.rangeCount; i++) { var range = selection.getRangeAt(i); if (designMode === 'on') { range.deleteContents(); } else { if (contentEditables.length) { contentEditables.forEach(node => { if (node.contains(range.commonAncestorContainer)) { range.deleteContents(); } }); } } } } } function pasteSelectedData(e) { if (e.target.contentEditable && e.target.setRangeText) { e.target.setRangeText("", e.target.selectionStart, e.target.selectionEnd, 'select'); e.target.setRangeText(SafeExamBrowser.clipboard.text, e.target.selectionStart, e.target.selectionStart + SafeExamBrowser.clipboard.text.length, 'end'); } else { var w = e.target.ownerDocument.defaultView; var designMode = e.target.ownerDocument.designMode; var contentEditables = e.target.ownerDocument.querySelectorAll('*[contenteditable]'); var selection = w.getSelection(); for (var i = 0; i < selection.rangeCount; i++) { var r = selection.getRangeAt(i); if (designMode === 'on') { r.deleteContents(); } else { if (contentEditables.length) { contentEditables.forEach(node => { if (node.contains(r.commonAncestorContainer)) { r.deleteContents(); } }); } } } if (designMode === 'on') { var range = w.getSelection().getRangeAt(0); if (SafeExamBrowser.clipboard.ranges.length > 0) { SafeExamBrowser.clipboard.ranges.map(r => { range = w.getSelection().getRangeAt(0); range.collapse(); const newNode = r.cloneNode(true); range.insertNode(newNode); range.collapse(); }); } else { range.collapse(); range.insertNode(w.document.createTextNode(SafeExamBrowser.clipboard.text)); range.collapse(); } } else { if (contentEditables.length) { contentEditables.forEach(node => { var range = w.getSelection().getRangeAt(0); if (node.contains(range.commonAncestorContainer)) { if (SafeExamBrowser.clipboard.ranges.length > 0) { SafeExamBrowser.clipboard.ranges.map(r => { range = w.getSelection().getRangeAt(0); range.collapse(); const newNode = r.cloneNode(true); range.insertNode(newNode); range.collapse(); }); } else { range = w.getSelection().getRangeAt(0); range.collapse(); range.insertNode(w.document.createTextNode(SafeExamBrowser.clipboard.text)); range.collapse(); } } }); } } } } function onCopy(e) { SafeExamBrowser.clipboard.clear(); try { copySelectedData(e); } finally { e.preventDefault(); e.returnValue = false; } return false; } function onCut(e) { SafeExamBrowser.clipboard.clear(); try { copySelectedData(e); cutSelectedData(e); } finally { e.preventDefault(); e.returnValue = false; } return false; } function onPaste(e) { try { pasteSelectedData(e); } finally { e.preventDefault(); e.returnValue = false; } return false; } window.document.addEventListener("copy", onCopy, true); window.document.addEventListener("cut", onCut, true); window.document.addEventListener("paste", onPaste, true);