Commit c5773736 authored by Robin Tissot's avatar Robin Tissot
Browse files

Trying to make diplo panel work.

parent 42e1fcba
......@@ -268,6 +268,7 @@ class LineViewSet(ModelViewSet):
if errors:
return Response(errors,
status=status.HTTP_400_BAD_REQUEST)
return Response(response)
# return Response(status=200, data=response)
......
......@@ -27,56 +27,47 @@ var diploLine = LineBase.extend({
}
},
methods: {
startEdit(ev){
// if we are selecting text we don't want to start editing
// to be able to do multiline selection
if (document.getSelection().toString()) {
return true;
}
this.$parent.setEditLine(this.line);
this.$parent.$parent.blockShortcuts = true;
},
stopEdit(ev) {
this.$parent.$parent.blockShortcuts = false;
},
setContent(content){
let id = this.line.pk;
if(this.line.currentTrans.content != content){
$("#" + id).text(content);
this.line.currentTrans.content = content;
}
cleanSource(dirtyText) {
// cleanup html and possibly other tags (?)
var tmp = document.createElement("DIV");
tmp.innerHTML = dirtyText;
let clean = tmp.textContent || tmp.innerText || "";
tmp.remove();
return clean;
},
onPaste(e){
onPaste(e) {
let pastedData = e.clipboardData.getData('text/plain');
let pasted_data_split = pastedData.split('\n');
if (pasted_data_split.length < 2) {
return
if (pasted_data_split.length == 1) {
// all of this just to call cleanSource on the data
let paste = (event.clipboardData || window.clipboardData).getData('text');
paste = this.cleanSource(paste);
const selection = window.getSelection();
if (!selection.rangeCount) return false;
selection.deleteFromDocument();
selection.getRangeAt(0).insertNode(document.createTextNode(paste));
} else {
e.preventDefault();
//remove the last line if it's empty
if (pasted_data_split[pasted_data_split.length - 1] == "")
if (pasted_data_split[pasted_data_split.length - 1] == "") {
pasted_data_split.pop();
}
let index = this.$parent.$children.indexOf(this);
for (let i = 1; i < pasted_data_split.length; i++) {
if (this.$parent.$children[index + i]) {
let content = pasted_data_split[i];
let child = this.$parent.$children[index + i];
child.setContent(content);
} else {
let content = pasted_data_split.slice(i - 1).join('\n');
let child = this.$parent.$children[index + 1];
child.setContent(content);
for (let i = 0; i < pasted_data_split.length; i++) {
let content = pasted_data_split[i];
let child = this.$parent.$children[index + i];
if (child) {
child.$el.textContent = this.cleanSource(content);
}
}
this.$parent.toggleSave();
}
e.preventDefault();
},
getContentOrFake() {
return this.line.currentTrans.content;
},
getRegion(){
getRegion() {
return this.$parent.part.regions.findIndex(r => r.pk == this.line.region);
}
}
......
var timer ;
var DiploPanel = BasePanel.extend({
data() { return {
editLine: null,
updatedLines : [],
createdLines : [],
movedLines:[],
......@@ -10,30 +9,28 @@ var DiploPanel = BasePanel.extend({
components: {
'diploline': diploLine,
},
mounted(){
Vue.nextTick(function() {
var vm = this ;
var el = document.getElementById('list');
sortable = Sortable.create(el, {
group: 'shared',
multiDrag: true,
multiDragKey : 'CTRL',
selectedClass: "selected",
animation: 150,
onEnd: function(/**Event*/evt) {
vm.onDragginEnd(evt);
}
});
}.bind(this));
},
/* mounted(){
* Vue.nextTick(function() {
* var vm = this ;
* var el = document.getElementById('list');
* sortable = Sortable.create(el, {
* group: 'shared',
* multiDrag: true,
* multiDragKey : 'CTRL',
* selectedClass: "selected",
* animation: 150,
* onEnd: function(evt) {
* vm.onDragginEnd(evt);
* }
* });
* }.bind(this));
* }, */
methods:{
toggleSave(){
clearTimeout(timer);
timer = setTimeout(function (){
this.save();
}.bind(this),
2000);
startEdit(ev){
this.$parent.blockShortcuts = true;
},
stopEdit(ev) {
this.$parent.blockShortcuts = false;
},
onDragginEnd(ev) {
/*
......@@ -57,99 +54,113 @@ var DiploPanel = BasePanel.extend({
this.moveLines();
},
moveLines(){
moveLines() {
if(this.movedLines.length != 0){
this.$parent.$emit('line:move',this.movedLines, function () {
this.$parent.$emit('line:move', this.movedLines, function () {
this.movedLines = [];
}.bind(this));
}
},
save(){
save() {
/*
if some lines are modified add them to updatedlines, new lines add them to createdLines then save
*/
if some lines are modified add them to updatedlines,
new lines add them to createdLines then save
*/
this.addToList();
this.bulkUpdate();
this.bulkCreate();
},
updateEditLine(position){
if(position < this.part.lines.length && position >= 0) {
this.setEditLine(this.part.lines[position]);
let nextLine = this.$children[position];
nextLine.startEdit();
this.setCursorPosition("[id='"+ this.editLine.pk+ "']");
}
},
setHeight() {
this.$el.querySelector('.content-container').style.maxHeight = Math.round(this.part.image.size[1] * this.ratio) + 'px';
},
onKeyDown(ev){
let index = this.part.lines.indexOf(this.editLine);
//disable shortcuts
this.$parent.blockShortcuts = true;
// click delete button if you are at the beggining of the line
// if(ev.keyCode==8 && this.getCursorPosition()==0){
// ev.preventDefault();
//
// this.updateEditLine(index -1);
// let idx = this.part.lines.indexOf(this.editLine);
// let child = this.$children[idx];
// let nextLine = this.part.lines[idx+1];
// let content = child.line.currentTrans.content + nextLine.currentTrans.content;
// child.setContent(content);
// this.addToUpdatedLines(child.line.currentTrans);
//
// for(let i=idx +1; i < this.part.lines.length; i++) {
//
// let child = this.$children[i];
// let nextLine = this.part.lines[i+1];
// let currentLine = child.line;
// if(nextLine){
//
// if(currentLine.currentTrans.pk){
// child.setContent(nextLine.currentTrans.content);
// this.addToUpdatedLines(currentLine.currentTrans);
//
// }
// else{
// child.setContent(nextLine.currentTrans.content);
// this.createdLines.push(currentLine.currentTrans);
// }
// }
// else {
// child.setContent("");
// this.addToUpdatedLines(child.line.currentTrans);
// }
// this.setCursorPosition("[id='"+ this.editLine.pk+ "']");
//
//
// }
// this.updateEditLine( -1);
//
//
// }
//click on enter button
if(ev.keyCode == 13){
ev.preventDefault();
let idx = this.part.lines.indexOf(this.editLine);
if(idx < this.part.lines.length -1){
this.updateEditLine(idx +1);
}
focusNextLine(sel, line) {
if (line.nextSibling) {
let range = document.createRange();
range.setStart(line.nextSibling, 0);
range.collapse(false);
sel.removeAllRanges();
sel.addRange(range);
}
if(ev.keyCode == 8){
this.toggleSave();
},
focusPreviousLine(sel, line) {
if (line.previousSibling) {
let range = document.createRange();
range.setStart(line.previousSibling, 0);
sel.removeAllRanges();
sel.addRange(range);
}
},
setEditLine(l) {
this.editLine = l;
onKeyPress(ev) {
// arrows needed to avoid skipping empty lines
if (ev.key == 'ArrowDown' && !ev.shiftKey) {
let sel = window.getSelection();
let div = sel.anchorNode.nodeType==Node.TEXT_NODE?sel.anchorNode.parentElement:sel.anchorNode;
this.focusNextLine(sel, div);
ev.preventDefault();
} else if (ev.key == 'ArrowUp' && !ev.shiftKey) {
let sel = window.getSelection();
let div = sel.anchorNode.nodeType==Node.TEXT_NODE?sel.anchorNode.parentElement:sel.anchorNode;
this.focusPreviousLine(sel, div);
ev.preventDefault();
} else if (ev.key == 'Enter') {
if (window.getSelection) {
const selection = window.getSelection();
let range = selection.getRangeAt(0);
// push text down
let lineNode = range.endContainer.nodeType==Node.TEXT_NODE?range.endContainer.parentNode:range.endContainer;
let lines = lineNode.parentNode.childNodes;
let curIndex = Array.prototype.indexOf.call(lines, lineNode);
let nextText = lineNode.textContent.slice(range.endOffset).trim();
this.$children[curIndex].$el.textContent = lineNode.textContent.slice(0, range.startOffset).trim();
for (let i=curIndex+1; i<lines.length-1; i++) {
let text = nextText;
nextText = lines[i].textContent;
this.$children[i].$el.textContent = text;
}
// focus next line
this.focusNextLine(selection, lineNode);
}
ev.preventDefault();
} else if (ev.key == 'Backspace') {
const selection = window.getSelection();
let range = selection.getRangeAt(0);
if (range.startContainer != range.endContainer) {
// override default behavior to avoid deleting entire lines
let startLine = range.startContainer.nodeType==Node.TEXT_NODE?range.startContainer.parentNode:range.startContainer;
let endLine = range.endContainer.nodeType==Node.TEXT_NODE?range.endContainer.parentNode:range.endContainer;
let inRange = false;
for (let i=0; i<this.$children.length; i++) {
let line = this.$children[i].$el;
if (line == startLine) {
line.textContent = line.textContent.slice(0, range.startOffset);
inRange = true;
} else if (line == endLine) {
line.textContent = line.textContent.slice(range.endOffset);
break;
} else if (inRange) {
line.textContent = '';
}
}
ev.preventDefault();
} else if (range.startOffset == 0 && range.endOffset == 0) {
// push text up
let lineNode = range.startContainer.nodeType==Node.TEXT_NODE?range.startContainer.parentNode:range.startContainer;
let lines = lineNode.parentNode.childNodes;
let curIndex = Array.prototype.indexOf.call(lines, lineNode);
if (curIndex > 0) {
// append content to previous line
this.$children[curIndex-1].$el.textContent += this.$children[curIndex].$el.textContent;
for (let i=curIndex; i<lines.length-1; i++) {
this.$children[i].$el.textContent = this.$children[i+1].$el.textContent;
}
this.$children[lines.length-1].$el.textContent = '';
}
ev.preventDefault();
}
}
},
bulkUpdate(){
bulkUpdate() {
if(this.updatedLines.length){
this.$parent.$emit(
'bulk_update:transcriptions',
......@@ -159,7 +170,7 @@ var DiploPanel = BasePanel.extend({
}.bind(this));
}
},
bulkCreate(){
bulkCreate() {
if(this.createdLines.length){
this.$parent.$emit(
'bulk_create:transcriptions',
......@@ -169,22 +180,24 @@ var DiploPanel = BasePanel.extend({
}.bind(this));
}
},
addToList(){
addToList() {
/*
parse all lines if the content changed, add it to updated lines
*/
for(let i=0;i<this.$children.length; i++) {
*/
for(let i=0; i<this.$children.length; i++) {
let currentLine = this.$children[i];
if(currentLine.line.currentTrans.content != currentLine.$refs.content[0].textContent){
currentLine.line.currentTrans.content = currentLine.$refs.content[0].textContent ;
if(currentLine.line.currentTrans.pk)
if(currentLine.line.currentTrans.content != currentLine.$el.textContent){
// TODO: sanitize text content?!
currentLine.line.currentTrans.content = currentLine.$el.textContent;
if(currentLine.line.currentTrans.pk) {
this.addToUpdatedLines(currentLine.line.currentTrans);
else
} else {
this.createdLines.push(currentLine.line.currentTrans);
}
}
}
},
addToUpdatedLines(lt){
addToUpdatedLines(lt) {
/*
if line already exists in updatedLines update its content on the list
*/
......@@ -202,47 +215,6 @@ var DiploPanel = BasePanel.extend({
*/
this.setHeight();
},
getCursorPosition() {
return window.getSelection().getRangeAt(0).startOffset;
},
setCursorPosition(id) {
const textNode = document.querySelector(id);
let sel = window.getSelection();
const range = document.createRange();
range.setStart(textNode,textNode.length ); // Start at first character
range.setEnd(textNode, textNode.length);
sel.removeAllRanges();
sel.addRange(range);
},
//return --> insert carriage return here and push rest of text of this line into the next line.
// If there is text in the next line push that line one down etc. If there is no text in the next line dont push further
carriage(ev,idx){
ev.preventDefault();
if (window.getSelection) {
let selection = window.getSelection(),
range = selection.getRangeAt(0),
br = document.createElement("br"),
textNode = document.createTextNode($("<div></div>").text()); //Passing " " directly will not end up being shown correctly
range.deleteContents();
range.insertNode(br);
range.collapse(false);
range.insertNode(textNode);
range.selectNodeContents(textNode);
selection.removeAllRanges();
selection.addRange(range);
let child = this.$children[idx+1];
let target = selection.anchorNode.nextSibling.parentNode ;
let html = target.innerHTML ;
let after_break = html.substring(html.indexOf('br')+3);
child.setContent(after_break + child.line.currentTrans.content);
target.innerHTML = html.substring(0, html.indexOf('<br')) + "</div>";
this.updateEditLine(idx+1);
return false;
}
}
},
});
......@@ -171,7 +171,9 @@ var partVM = new Vue({
$alertsContainer.on('part:mask', function(ev, data) {
data.lines.forEach(function(lineData) {
let line = this.part.lines.find(l=>l.pk == lineData.pk);
line.mask = lineData.mask;
if (line) { // might have been deleted in the meantime
line.mask = lineData.mask;
}
}.bind(this));
}.bind(this));
},
......
......@@ -590,24 +590,35 @@ i.panel-icon {
padding: 10px;
}
.table-row {
/*border-right: 1px solid lightgrey;*/
padding-left: 2%;
padding-right: 2%;
#diplo-panel .content-container {
overflow-y: auto;
}
#diplomatic-lines {
counter-reset: line;
}
#diplomatic-lines div.line-content {
display: block;
line-height: 1.7rem;
margin-bottom: 0px;
overflow-wrap: break-word;
margin-left: 50px;
}
.line-order, .line-region{
#diplomatic-lines .line-content:before {
user-select: none;
width: 15%;
text-align: center;
border-right: 1px solid lightgrey;
counter-increment: line;
content: counter(line);
display: inline-block;
border-right: 1px solid #ddd;
padding: 0 .5em;
margin-right: .5em;
width: 50px;
margin-left: -50px;
color: #888;
}
.line-content {
margin-bottom: 0px;
overflow-wrap: break-word;
flex-basis: 85%;
}
.line-selected {
background-color:#33A2FF;
border: solid #33A2FF 1px;
......
......@@ -541,46 +541,41 @@
</keep-alive>
<keep-alive>
<DiploPanel v-if="show.diplomatic" v-bind:part="part" ref="diploPanel" inline-template>
<div class="col panel">
<div class="tools">
<i title="{% trans 'Transcription Panel' %}" class="panel-icon fas fa-language"></i>
</div>
<div v-if="part" id="diplomatic-lines" contenteditable
@keyup="toggleSave"
class="content-container {{ document.read_direction }}">
<div id="list" class="list-group">
<DiploPanel id="diplo-panel"
v-bind:part="part"
v-if="show.diplomatic && part.loaded"
ref="diploPanel"
inline-template>
<div class="col panel">
<div class="tools">
<i title="{% trans 'Transcription Panel' %}" class="panel-icon fas fa-language"></i>
</div>
<div class="content-container {{ document.read_direction }}">
<div id="diplomatic-lines"
contenteditable="true"
@keydown="onKeyPress"
@focusin="startEdit"
@focusout="stopEdit"
@blur="save">
<diploline v-for="line in part.lines"
v-bind:line="line"
v-bind:ratio="ratio"
v-bind:key="line.pk"
v-bind:key="'DL' + line.pk"
inline-template>
<div class="d-flex flex-row">
{# <div class ="table-row line-region " class="w-10" contenteditable="false">${showregion}</div>#}
<div class ="table-row line-order w-10"
contenteditable="false"
>${line.order + 1}</div>
<p v-bind:id="line.pk"
v-if="line.currentTrans"
@mouseup="startEdit"
@focusout="stopEdit"
@mouseover="showOverlay"
@mouseleave="hideOverlay"
@select="stopEdit"
{# @paste="onPaste"#}
class="table-row line-content"
ref="content"
v-html="line.currentTrans.content"></p>
</div>
<div class="line-content"
v-if="line.currentTrans"
@mouseover="showOverlay"
@mouseleave="hideOverlay"
@paste="onPaste"
ref="content"
v-html="line.currentTrans.content">
</div>
</diploline>
</div>
</div>
</div>
</DiploPanel>
</keep-alive>
</div>
</DiploPanel>
</keep-alive>
<div class="col-sides">
{% if document.read_direction == 'rtl' %}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment