-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathepa-translation.js
117 lines (113 loc) · 4.94 KB
/
epa-translation.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
(function(w,d)
{
d.addEventListener('DOMContentLoaded', ()=>
{
let dictionaryName = "anonymous"
, editedEl;
const scopeSelector = "epa-translation"
, $conf = getConfigNode()
, css = ` { position:absolute; right:1em; top:0; text-align:right; z-index:10; }
form,
#epa-translation-visibility,
.epa-translation-edit span{ display:none; }
.epa-translation-edit input:checked ~span,
#epa-translation-visibility:checked ~form { display:block; }
form,
>label{background-color: white; margin:0; padding: 0.5em; }
form{ border: 2px silver solid; border-radius: 0.2em; }
form>label{display:block;}
`.split('\n').map( s => s.trim() && `${scopeSelector} ${s}` ).join('\n')
, html = `<style> *[contentEditable=true],
*[contentEditable=true] *[contentEditable=false]{background-color:aqua}
*[contentEditable=true]:focus{background-color:aquamarine}
/**[contentEditable=false] *:focus{background-color:aquamarine}*/
${css}
</style>
<input type="checkbox" id="epa-translation-visibility" />
<label for="epa-translation-visibility">🏳 Languages</label>
<form>
<label
class="epa-translation-edit"
accesskey="t"
title="Trigger Translation Editor mode
ALT+T or CTRL+ALT+T"
><input type="checkbox"/> <u><b>T</b></u>ranslation editor mode
<span>Click two times on text for translation to get a cursor. </span>
</label>
<label class="epa-trans-props-lang"> Language <input type="text" value="unknown"/></label>
<label class="epa-trans-props-dict"> Dictionary URL <input type="text" placeholder="" /></label>
</form>
`;
$conf.innerHTML = html;
$on( $conf,'.epa-translation-edit', 'change', ev => setEditorMode( ev.target.checked ) );
// use MutationObserver for 'epa-translation,.epa-translation' changes
function
setEditorMode( bEnable )
{
document.body[ bEnable? 'addEventListener': 'removeEventListener']( 'click',clickInEditMode,true );
document.body[ bEnable? 'addEventListener': 'removeEventListener']( 'input',inputInEditMode,true );
document.body[ bEnable? 'addEventListener': 'removeEventListener']( 'blur' , blurInEditMode,true );
bEnable || document.body.querySelectorAll('*[contentEditable]').forEach( el=> el.removeAttribute('contentEditable'));
}
function
clickInEditMode(ev)
{
let el = ev.target;
const elChanged = el !== editedEl;
elChanged && clearContentEditable( editedEl );
editedEl = el;
let t = el.origText;
if( !t )
el.origText = el.innerText;
el.contentEditable = "true";
if( el.children )
for( let c of el.children )
c.contentEditable = "false";
while( el = el.parentNode )
if( el.isContentEditable )
el.contentEditable = "false";
// if( elChanged )
// ev.preventDefault();
}
function
inputInEditMode(ev)
{
const el = ev.target
, txt = el.innerText;
if( txt === el.origText || txt === el.savedText )
return;
localStorage.setItem( getStorageKey(el.origText), el.savedText=txt );
}
function
blurInEditMode(ev)
{
clearContentEditable(ev.target)
}
function
clearContentEditable( el )
{ if( !el )
return;
if( el.origText && el.innerText === el.origText )
el.contentEditable = "inherit";
if( el.children )
for( let c of el.children )
c.contentEditable = "false";
}
function
getStorageKey( txt )
{
return `epa-translation|${dictionaryName}|${txt}`;
}
function
getConfigNode()
{
const translations = d.getElementsByTagName('epa-translation');
return translations[0] || d.body.appendChild( document.createElement('epa-translation') );
}
});
function
$on( el, css, event, cb )
{
el.querySelector(css).addEventListener( event, cb );
}
})(window,document);