diff --git a/front/vue/components/DiploPanel.vue b/front/vue/components/DiploPanel.vue index 82409240c3d97e54fa341ce7953f0d8dbfc8d93d..e14f4e9e822f353341cdd6264126479e68fb4065 100644 --- a/front/vue/components/DiploPanel.vue +++ b/front/vue/components/DiploPanel.vue @@ -87,6 +87,8 @@ export default Vue.extend({ }.bind(this)); this.refresh(); + + }, methods: { empty() { @@ -250,35 +252,143 @@ export default Vue.extend({ tmp.remove(); return clean; }, + onPaste(e) { - let pastedData = e.clipboardData.getData('text/plain'); - let pasted_data_split = pastedData.split('\n'); + + let diplomaticLines=document.querySelector("#diplomatic-lines"); + let sel = window.getSelection(); + let tmpDiv = document.createElement('div'); - if (pasted_data_split.length == 1) { - let content = this.cleanSource(pastedData); - document.execCommand('insertText', false, content); - } else { - const selection = window.getSelection(); - let range = selection.getRangeAt(0); - let target = range.startContainer.nodeType==Node.TEXT_NODE?range.startContainer.parentNode:range.startContainer; - let start = Array.prototype.indexOf.call(this.$refs.diplomaticLines.children, target); - let newDiv, child = this.$refs.diplomaticLines.children[start]; - for (let i = 0; i < pasted_data_split.length; i++) { - newDiv = this.appendLine(child); - newDiv.textContent = this.cleanSource(pasted_data_split[i]); - // trick to get at least 'some' ctrl+z functionality - // this fails in spectacular ways differently in firefox and chrome... so no ctrl+z - /* range.setStart(newDiv, 0); - * selection.removeAllRanges(); - * selection.addRange(range); - * document.execCommand("insertText", false, this.cleanSource(content)); */ + let pastedData; + if (e && e.clipboardData && e.clipboardData.types && e.clipboardData.getData) { + let types = e.clipboardData.types; + if (((types instanceof DOMStringList) && types.contains("text/html")) || (types.indexOf && types.indexOf('text/html') !== -1)) { + let content = e.clipboardData.getData('text/html'); + tmpDiv.innerHTML = content; + pastedData = [ ...tmpDiv.childNodes].map(e=>e.textContent).join('\n'); + } else { + pastedData = e.clipboardData.getData('text/plain'); + } + + var cursor = sel.getRangeAt(0); // specific posiiton or range + // for a range, delete content to clean data and to get resulting specific cursor position from it: + cursor.deleteContents(); // if selection is done on several lines, cursor caret be placed between 2 divs + + // after deleting (for an range), + // check if resulting cursor is in or off a line div or some errors will occur!: + let parentEl = sel.getRangeAt(0).commonAncestorContainer; + if (parentEl.nodeType != 1) { + parentEl = parentEl.parentNode; // for several different lines, commonAncestorContainer does not exist + } + + let pasted_data_split = pastedData.split("\n"); + let refNode = parentEl; + + let textBeforeCursor = ''; + let textAfterCursor = ''; + + // nodes which will be placed before and after the targetnode - where text is pasted (new node or current node) + let prevSibling; + let nextSibling; + + if(parentEl.id == 'diplomatic-lines'){ // if parent node IS the main diplomatic panel div = cursor is offline + // occurs when a selection is made on several lines or all is selected + + //we create a between node: + refNode = document.createElement('div'); + refNode.textContent = ''; + + // paste text on the selection (cursor position or range): + cursor.insertNode(refNode); + + // set caret position/place the cursor into the new node: + cursor.setStart(refNode,0); + cursor.setEnd(refNode,0); + + // in this case, contents before and after selection will belong to near siblings + if(refNode.previousSibling != null){ + prevSibling = refNode.previousSibling; + } + if(refNode.nextSibling != null){ + nextSibling = refNode.nextSibling; + } + } + + // get current cursor position withing the line div tag + let caretPos = cursor.endOffset; // 4 // nombre de caractères du début jusqu'à la position du curseur + + // store previous and next text in the line to it / for a selection wihtin on line: + textBeforeCursor = refNode.textContent.substring(0, caretPos); + textAfterCursor = refNode.textContent.substring(caretPos, refNode.textContent.length); + + // for a selection between several lines, contents before and after will be the contents of siblings + // to avoid create new lines before and after, fusion of sibling contents to the current node and removing it + if(typeof(prevSibling) != "undefined"){ + textBeforeCursor = prevSibling.textContent; + prevSibling.parentNode.removeChild(prevSibling); + } + if(typeof(nextSibling) != "undefined"){ + textAfterCursor = nextSibling.textContent; + nextSibling.parentNode.removeChild(nextSibling); + } + + let endPos = 0; // will set the new cursor position + let lastTargetNode = refNode; // last impacted node for a copy-paste (for several lines) + + if(pasted_data_split.length == 1){ + refNode.textContent = textBeforeCursor + pasted_data_split[0] + textAfterCursor; + endPos = String(textBeforeCursor + pasted_data_split[0]).length; + } + else{ + // store resulting firstLine & lastLine contents regarding cursor position + let firstLine = textBeforeCursor + pasted_data_split[0]; + let lastLine = pasted_data_split[pasted_data_split.length -1] + textAfterCursor; + let nextNodesContents = new Array(); + + for(var j=0; j < pasted_data_split.length; j++) + { + var lineContent = pasted_data_split[j]; + if(j == 0) + lineContent = firstLine; + if(j == pasted_data_split.length-1) + lineContent = lastLine; + nextNodesContents.push(lineContent); + } + // get length of last pasted line to set new caret position + endPos = String(pasted_data_split[pasted_data_split.length-1]).length; + + refNode.textContent = nextNodesContents[nextNodesContents.length-1]; + lastTargetNode = refNode; + + nextNodesContents = nextNodesContents.reverse(); + + for(var j=1; j < nextNodesContents.length; j++) // for any other line, we add a div and set this content + { + var prevLineDiv = document.createElement('div'); + prevLineDiv.textContent = nextNodesContents[j]; + // add the new line as a next neighbor of current div: + refNode = diplomaticLines.insertBefore(prevLineDiv, refNode); + } } + // set the caret position right after the pasted content: + + if(typeof(lastTargetNode.childNodes[0]) != "undefined") + { + let textNode = lastTargetNode.childNodes[0]; + cursor.setStart(textNode, endPos); + } + + } else { + // not sure if this can actually happen in firefox/chrome?! + pastedData = ""; + // so we do nothing; keeping original content } - this.$refs.saveNotif.classList.remove('hide'); - this.constrainLineNumber(); + // Stop the data from actually being pasted // without it will paste the native copied text after "content" + e.stopPropagation(); e.preventDefault(); }, + showOverlay(ev) { let target = ev.target.nodeType==Node.TEXT_NODE?ev.target.parentNode:ev.target; let index = Array.prototype.indexOf.call(target.parentNode.children, target);