Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
scripta
eScriptorium
Commits
4b8792f0
Commit
4b8792f0
authored
Sep 02, 2020
by
Robin Tissot
Browse files
fully working prototype (no reordering).
parent
c5773736
Changes
4
Hide whitespace changes
Inline
Side-by-side
app/apps/core/static/js/edit/components/diplo_line.js
View file @
4b8792f0
...
...
@@ -14,8 +14,13 @@ var diploLine = LineBase.extend({
}
}
},
mounted
()
{
Vue
.
nextTick
(
function
()
{
this
.
$parent
.
appendLine
();
}.
bind
(
this
));
},
watch
:
{
'
line.order
'
:
function
(
o
,
n
)
{
'
line.order
'
:
function
(
n
,
o
)
{
// make sure it's at the right place,
// in case it was just created or the ordering got recalculated
let
index
=
Array
.
from
(
this
.
$el
.
parentNode
.
children
).
indexOf
(
this
.
$el
);
...
...
@@ -24,48 +29,17 @@ var diploLine = LineBase.extend({
this
.
$el
,
this
.
$el
.
parentNode
.
children
[
this
.
line
.
order
]);
}
},
'
line.currentTrans
'
:
function
(
n
,
o
)
{
let
line
=
this
.
getEl
();
if
(
n
!=
undefined
&&
n
.
content
)
{
line
.
textContent
=
n
.
content
;
}
}
},
methods
:
{
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
)
{
let
pastedData
=
e
.
clipboardData
.
getData
(
'
text/plain
'
);
let
pasted_data_split
=
pastedData
.
split
(
'
\n
'
);
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
{
//remove the last line if it's empty
if
(
pasted_data_split
[
pasted_data_split
.
length
-
1
]
==
""
)
{
pasted_data_split
.
pop
();
}
let
index
=
this
.
$parent
.
$children
.
indexOf
(
this
);
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
);
}
}
}
e
.
preventDefault
();
},
getContentOrFake
()
{
return
this
.
line
.
currentTrans
.
content
;
getEl
()
{
return
this
.
$parent
.
editor
.
querySelector
(
'
div:nth-child(
'
+
parseInt
(
this
.
line
.
order
+
1
)
+
'
)
'
);
},
getRegion
()
{
return
this
.
$parent
.
part
.
regions
.
findIndex
(
r
=>
r
.
pk
==
this
.
line
.
region
);
...
...
app/apps/core/static/js/edit/components/diplo_panel.js
View file @
4b8792f0
var
timer
;
var
DiploPanel
=
BasePanel
.
extend
({
data
()
{
return
{
updatedLines
:
[],
...
...
@@ -9,38 +8,90 @@ 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(evt) {
* vm.onDragginEnd(evt);
* }
* });
* }.bind(this));
* }, */
methods
:{
startEdit
(
ev
){
created
()
{
// vue.js quirck, have to dinamically create the event handler
// call save every 10 seconds after last change
this
.
debouncedSave
=
_
.
debounce
(
function
()
{
this
.
save
();
}.
bind
(
this
),
10000
);
},
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));
*/
this
.
editor
=
this
.
$el
.
querySelector
(
'
#diplomatic-lines
'
);
this
.
saveNotif
=
this
.
$el
.
querySelector
(
'
.tools #save-notif
'
);
},
methods
:
{
changed
()
{
this
.
saveNotif
.
classList
.
remove
(
'
hide
'
);
this
.
debouncedSave
();
},
appendLine
(
pos
)
{
let
div
=
document
.
createElement
(
'
div
'
);
div
.
appendChild
(
document
.
createElement
(
'
br
'
));
if
(
pos
===
undefined
)
{
this
.
editor
.
appendChild
(
div
);
}
else
{
this
.
editor
.
insertBefore
(
div
,
pos
.
nextSibling
);
}
return
div
;
},
constrainLineNumber
()
{
// add lines untill we have enough of them
while
(
this
.
editor
.
childElementCount
<
this
.
part
.
lines
.
length
)
{
this
.
appendLine
();
}
// need to add/remove danger indicators
for
(
let
i
=
0
;
i
<
this
.
editor
.
childElementCount
;
i
++
)
{
let
line
=
this
.
editor
.
querySelector
(
'
div:nth-child(
'
+
parseInt
(
i
+
1
)
+
'
)
'
);
if
(
line
===
null
)
{
this
.
editor
.
children
[
i
].
remove
();
continue
;
}
if
(
i
<
this
.
part
.
lines
.
length
)
{
line
.
classList
.
remove
(
'
alert-danger
'
);
line
.
setAttribute
(
'
title
'
,
''
);
}
else
if
(
i
>=
this
.
part
.
lines
.
length
)
{
if
(
line
.
textContent
==
''
)
{
// just remove empty lines
line
.
remove
();
}
else
{
line
.
classList
.
add
(
'
alert-danger
'
);
line
.
setAttribute
(
'
title
'
,
'
More lines than there is in the segmentation!
'
);
}
}
}
},
startEdit
(
ev
)
{
this
.
$parent
.
blockShortcuts
=
true
;
},
stopEdit
(
ev
)
{
this
.
$parent
.
blockShortcuts
=
false
;
this
.
constrainLineNumber
();
this
.
save
();
},
onDragginEnd
(
ev
)
{
/*
Finish dragging lines, save new positions
*/
Finish dragging lines, save new positions
*/
if
(
ev
.
newIndicies
.
length
==
0
&&
ev
.
newIndex
!=
ev
.
oldIndex
){
let
pk
=
ev
.
item
.
querySelector
(
'
.line-content
'
).
id
;
let
elt
=
{
"
pk
"
:
pk
,
"
index
"
:
ev
.
newIndex
};
this
.
movedLines
.
push
(
elt
);
}
else
{
for
(
let
i
=
0
;
i
<
ev
.
newIndicies
.
length
;
i
++
){
...
...
@@ -63,9 +114,10 @@ var DiploPanel = BasePanel.extend({
},
save
()
{
/*
if some lines are modified add them to updatedlines,
if some lines are modified add them to updatedlines,
new lines add them to createdLines then save
*/
this
.
saveNotif
.
classList
.
add
(
'
hide
'
);
this
.
addToList
();
this
.
bulkUpdate
();
this
.
bulkCreate
();
...
...
@@ -90,6 +142,7 @@ var DiploPanel = BasePanel.extend({
sel
.
addRange
(
range
);
}
},
onKeyPress
(
ev
)
{
// arrows needed to avoid skipping empty lines
if
(
ev
.
key
==
'
ArrowDown
'
&&
!
ev
.
shiftKey
)
{
...
...
@@ -102,64 +155,61 @@ var DiploPanel = BasePanel.extend({
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
'
)
{
}
},
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
)
{
let
pastedData
=
e
.
clipboardData
.
getData
(
'
text/plain
'
);
let
pasted_data_split
=
pastedData
.
split
(
'
\n
'
);
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
);
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
=
''
;
let
target
=
range
.
startContainer
.
nodeType
==
Node
.
TEXT_NODE
?
range
.
startContainer
.
parentNode
:
range
.
startContainer
;
let
start
=
Array
.
prototype
.
indexOf
.
call
(
target
.
parentNode
.
children
,
target
);
for
(
let
i
=
0
;
i
<
pasted_data_split
.
length
;
i
++
)
{
let
content
=
pasted_data_split
[
i
];
let
child
=
target
.
parentNode
.
children
[
start
+
i
];
let
newDiv
;
if
(
child
)
{
newDiv
=
this
.
appendLine
(
child
);
}
else
{
newDiv
=
this
.
appendLine
();
}
ev
.
preventDefault
();
// trick to get at least 'some' ctrl+z functionality
range
.
setStart
(
newDiv
,
0
);
selection
.
removeAllRanges
();
selection
.
addRange
(
range
);
document
.
execCommand
(
"
insertText
"
,
false
,
this
.
cleanSource
(
content
));
}
}
this
.
constrainLineNumber
();
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
);
if
(
index
>
-
1
&&
index
<
this
.
$children
.
length
)
{
this
.
$children
[
index
].
showOverlay
();
}
else
{
this
.
hideOverlay
();
}
},
hideOverlay
()
{
this
.
$children
[
0
].
hideOverlay
();
},
bulkUpdate
()
{
if
(
this
.
updatedLines
.
length
){
this
.
$parent
.
$emit
(
...
...
@@ -186,9 +236,8 @@ var DiploPanel = BasePanel.extend({
*/
for
(
let
i
=
0
;
i
<
this
.
$children
.
length
;
i
++
)
{
let
currentLine
=
this
.
$children
[
i
];
if
(
currentLine
.
line
.
currentTrans
.
content
!=
currentLine
.
$el
.
textContent
){
// TODO: sanitize text content?!
currentLine
.
line
.
currentTrans
.
content
=
currentLine
.
$el
.
textContent
;
if
(
currentLine
.
line
.
currentTrans
.
content
!=
currentLine
.
getEl
().
textContent
){
currentLine
.
line
.
currentTrans
.
content
=
currentLine
.
getEl
().
textContent
;
if
(
currentLine
.
line
.
currentTrans
.
pk
)
{
this
.
addToUpdatedLines
(
currentLine
.
line
.
currentTrans
);
}
else
{
...
...
@@ -199,7 +248,7 @@ var DiploPanel = BasePanel.extend({
},
addToUpdatedLines
(
lt
)
{
/*
if line already exists in updatedLines update its content on the list
if line already exists in updatedLines update its content on the list
*/
let
elt
=
this
.
updatedLines
.
find
(
l
=>
l
.
pk
===
lt
.
pk
);
if
(
elt
==
undefined
)
{
...
...
@@ -211,7 +260,7 @@ var DiploPanel = BasePanel.extend({
},
updateView
()
{
/*
update the size of the panel
update the size of the panel
*/
this
.
setHeight
();
},
...
...
app/escriptorium/static/css/escriptorium.css
View file @
4b8792f0
...
...
@@ -206,6 +206,14 @@ form.inline-form {
opacity
:
.5
;
}
.tools
.notice
{
color
:
var
(
--warning
);
border
:
1px
solid
;
padding
:
.25rem
.5rem
;
border-radius
:
.2rem
;
float
:
right
;
}
.help.open
:hover
{
opacity
:
1
;
}
...
...
@@ -596,8 +604,9 @@ i.panel-icon {
}
#diplomatic-lines
{
counter-reset
:
line
;
line-clamp
:
10
;
}
#diplomatic-lines
div
.line-content
{
#diplomatic-lines
div
{
display
:
block
;
line-height
:
1.7rem
;
margin-bottom
:
0px
;
...
...
@@ -605,7 +614,7 @@ i.panel-icon {
margin-left
:
50px
;
}
#diplomatic-lines
.line-content
:before
{
#diplomatic-lines
div
:before
{
user-select
:
none
;
text-align
:
center
;
counter-increment
:
line
;
...
...
app/escriptorium/templates/core/document_part_edit.html
View file @
4b8792f0
...
...
@@ -548,29 +548,27 @@
inline-template
>
<div
class=
"col panel"
>
<div
class=
"tools"
>
<i
title=
"{% trans 'Transcription Panel' %}"
class=
"panel-icon fas fa-language"
></i>
<i
title=
"{% trans 'Transcription Panel' %}"
class=
"panel-icon fas fa-list-ol"
></i>
<i
id=
"save-notif"
title=
"{% trans "
There
is
content
waiting
to
be
saved
(
don
'
t
leave
the
page
)"
%}"
class=
"notice fas fa-save hide"
></i>
</div>
<div
class=
"content-container {{ document.read_direction }}"
>
<diploline
v-for=
"line in part.lines"
v-bind:line=
"line"
v-bind:ratio=
"ratio"
v-bind:key=
"'DL' + line.pk"
>
</diploline>
<div
id=
"diplomatic-lines"
contenteditable=
"true"
@
keydown=
"onKeyPress"
@
keyup=
"constrainLineNumber"
@
input=
"changed"
@
focusin=
"startEdit"
@
focusout=
"stopEdit"
@
blur=
"save"
>
<diploline
v-for=
"line in part.lines"
v-bind:line=
"line"
v-bind:ratio=
"ratio"
v-bind:key=
"'DL' + line.pk"
inline-template
>
<div
class=
"line-content"
v-if=
"line.currentTrans"
@
mouseover=
"showOverlay"
@
mouseleave=
"hideOverlay"
@
paste=
"onPaste"
ref=
"content"
v-html=
"line.currentTrans.content"
>
</div>
</diploline>
@
mousemove=
"showOverlay"
@
mouseleave=
"hideOverlay"
@
paste=
"onPaste"
>
</div>
</div>
</div>
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment