This commit is contained in:
Sébastien Thuret 2021-10-08 19:02:30 +02:00
parent 0214d7bfd6
commit f5bc2bc3f5
No known key found for this signature in database
GPG key ID: 4742E2D66933BB08
2 changed files with 50 additions and 20 deletions

View file

@ -124,6 +124,13 @@ h3.header {
cursor: pointer; cursor: pointer;
} }
.btn-blue {
color: #42A5F5;
}
.btn-action:disabled {
color: #777;
}
.btn-action span { .btn-action span {
padding-right: 0.5rem; padding-right: 0.5rem;
} }

View file

@ -126,7 +126,7 @@
<template v-for="option in langs"> <template v-for="option in langs">
<option v-if="option.code !== 'auto'" :value="option.code">[[ option.name ]]</option> <option v-if="option.code !== 'auto'" :value="option.code">[[ option.name ]]</option>
</template> </template>
</select> </select>
</div> </div>
</div> </div>
@ -134,11 +134,11 @@
<div class="input-field textarea-container col s6"> <div class="input-field textarea-container col s6">
<label for="textarea1" class="sr-only"> <label for="textarea1" class="sr-only">
Text to translate Text to translate
</label> </label>
<textarea id="textarea1" v-model="inputText" @input="handleInput" ref="inputTextarea" dir="auto"></textarea> <textarea id="textarea1" v-model="inputText" @input="handleInput" ref="inputTextarea" dir="auto"></textarea>
<button class="btn-delete-text" title="Delete text" @click="deleteText"> <button class="btn-delete-text" title="Delete text" @click="deleteText">
<i class="material-icons">close</i> <i class="material-icons">close</i>
</button> </button>
<div class="characters-limit-container" v-if="charactersLimit !== -1"> <div class="characters-limit-container" v-if="charactersLimit !== -1">
<label>[[ inputText.length ]] / [[ charactersLimit ]]</label> <label>[[ inputText.length ]] / [[ charactersLimit ]]</label>
</div> </div>
@ -147,24 +147,26 @@
<div class="input-field textarea-container col s6"> <div class="input-field textarea-container col s6">
<label for="textarea2" class="sr-only"> <label for="textarea2" class="sr-only">
Translated text Translated text
</label> </label>
<textarea id="textarea2" v-model="translatedText" ref="translatedTextarea" dir="auto" readonly></textarea> <textarea id="textarea2" v-model="translatedText" ref="translatedTextarea" dir="auto" v-bind:readonly="!isSuggesting"></textarea>
<div class="actions"> <div class="actions">
<button v-if="inputText.length && !isSuggesting" class="btn-action" @click="suggestTranslation"> <button v-if="inputText.length && !isSuggesting" class="btn-action" @click="suggestTranslation">
<i class="material-icons">edit</i> <i class="material-icons">edit</i>
</button> </button>
<button v-if="inputText.length && isSuggesting" class="btn-action" @click="closeSuggestTranslation"> <button v-if="inputText.length && isSuggesting" class="btn-action btn-blue" @click="closeSuggestTranslation">
<i class="material-icons">close</i> <span>Cancel</span>
</button> </button>
<button v-if="inputText.length && isSuggesting" :disabled="!canSendSuggestion" class="btn-action btn-blue" @click="sendSuggestion">
<button class="btn-action btn-copy-translated" @click="copyText"> <span>Send</span>
</button>
<button v-if="!isSuggesting" class="btn-action btn-copy-translated" @click="copyText">
<span>[[ copyTextLabel ]]</span> <i class="material-icons">content_copy</i> <span>[[ copyTextLabel ]]</span> <i class="material-icons">content_copy</i>
</button> </button>
</div> </div>
<div class="position-relative"> <div class="position-relative">
<div class="progress translate" v-if="loadingTranslation"> <div class="progress translate" v-if="loadingTranslation">
<div class="indeterminate"></div> <div class="indeterminate"></div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
@ -346,7 +348,7 @@
if (this.charactersLimit !== -1 && this.inputText.length >= this.charactersLimit){ if (this.charactersLimit !== -1 && this.inputText.length >= this.charactersLimit){
this.inputText = this.inputText.substring(0, this.charactersLimit); this.inputText = this.inputText.substring(0, this.charactersLimit);
} }
// Update "selected" attribute (to overcome a vue.js limitation) // Update "selected" attribute (to overcome a vue.js limitation)
// but properly display checkmarks on supported browsers. // but properly display checkmarks on supported browsers.
// Also change the <select> width value depending on the <option> length // Also change the <select> width value depending on the <option> length
@ -355,7 +357,7 @@
if (el.value === this.sourceLang){ if (el.value === this.sourceLang){
el.setAttribute('selected', ''); el.setAttribute('selected', '');
this.$refs.sourceLangDropdown.style.width = getTextWidth(el.text) + 24 + 'px'; this.$refs.sourceLangDropdown.style.width = getTextWidth(el.text) + 24 + 'px';
}else{ }else{
el.removeAttribute('selected'); el.removeAttribute('selected');
} }
} }
@ -366,9 +368,9 @@
this.$refs.targetLangDropdown.style.width = getTextWidth(el.text) + 24 + 'px'; this.$refs.targetLangDropdown.style.width = getTextWidth(el.text) + 24 + 'px';
}else{ }else{
el.removeAttribute('selected'); el.removeAttribute('selected');
} }
} }
}, },
computed: { computed: {
requestCode: function(){ requestCode: function(){
@ -388,8 +390,11 @@
isHtml: function(){ isHtml: function(){
return htmlRegex.test(this.inputText); return htmlRegex.test(this.inputText);
} },
}, canSendSuggestion() {
return this.translatedText.trim() !== "" && this.translatedText !== this.inputText;
}
},
filters: { filters: {
escape: function(v){ escape: function(v){
return v.replace('"', '\\\"'); return v.replace('"', '\\\"');
@ -405,7 +410,9 @@
this.transRequest = null; this.transRequest = null;
} }
}, },
swapLangs: function(){ swapLangs: function(e){
this.closeSuggestTranslation(e)
var t = this.sourceLang; var t = this.sourceLang;
this.sourceLang = this.targetLang; this.sourceLang = this.targetLang;
this.targetLang = t; this.targetLang = t;
@ -417,6 +424,8 @@
this.error = ''; this.error = '';
}, },
handleInput: function(e){ handleInput: function(e){
this.closeSuggestTranslation(e)
if (this.timeout) clearTimeout(this.timeout); if (this.timeout) clearTimeout(this.timeout);
this.timeout = null; this.timeout = null;
@ -494,6 +503,20 @@
e.preventDefault(); e.preventDefault();
this.isSuggesting = false; this.isSuggesting = false;
},
sendSuggestion: function(e) {
e.preventDefault();
var request = new XMLHttpRequest();
self.transRequest = request;
var data = new FormData();
data.append("q", self.inputText);
data.append("s", self.inputText);
data.append("source", self.sourceLang);
data.append("target", self.targetLang);
request.open('POST', BaseUrl + '/translate', true);
}, },
deleteText: function(e){ deleteText: function(e){
e.preventDefault(); e.preventDefault();
@ -510,7 +533,7 @@
ctx.font = 'bold 16px sans-serif'; ctx.font = 'bold 16px sans-serif';
var textWidth = Math.ceil(ctx.measureText(text).width); var textWidth = Math.ceil(ctx.measureText(text).width);
return textWidth; return textWidth;
} }
function setApiKey(){ function setApiKey(){
var prevKey = localStorage.getItem("api_key") || ""; var prevKey = localStorage.getItem("api_key") || "";
@ -520,7 +543,7 @@
localStorage.setItem("api_key", newKey); localStorage.setItem("api_key", newKey);
} }
// @license-end // @license-end
</script> </script>
</body> </body>