|
<!DOCTYPE html> |
|
<html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|
<title>Manga Image Translator</title> |
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/picnic"> |
|
<style type="text/css"> |
|
#drop-area { border: 2px dashed #ccc; border-radius: 20px; width: 100%; margin: 50px auto; padding: 20px; } #drop-area.highlight { border-color: purple; } p { margin-top: 0; } .my-form { margin-bottom: 10px; } #gallery { text-align: center;} #gallery img { width: 95%; margin-bottom: 10px; vertical-align: middle; } .btn { display: inline-block; padding: 10px; background: #ccc; cursor: pointer; border-radius: 5px; border: 1px solid #ccc; } .btn:hover { background: #ddd; } #fileElem { display: none; } |
|
.no-drag-select { |
|
user-drag: none; |
|
user-select: none; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div> |
|
<nav class="demo"> |
|
<a href="#" class="brand">Manga Image Translator</a> |
|
|
|
|
|
<input id="bmenug" type="checkbox" class="show"> |
|
<label for="bmenug" class="burger pseudo button">≡</label> |
|
|
|
<div class="menu"> |
|
<a href="https://github.com/zyddnys/manga-image-translator" target="_blank">About</a> |
|
</div> |
|
</nav> |
|
|
|
<div class="flex one one-600 two-900" style="margin-top: 4em;"> |
|
<div style="margin:50px auto"> |
|
<div class="flex two" id="inputArea"> |
|
<div id="s-area"><h2>Raw Text</h2></div> |
|
<div id="t-area"><h2>Translation</h2></div> |
|
</div> |
|
<div> |
|
<button type="button" id="submit-button" class="button" disabled="disabled" name="submit" onclick="submit()">Waiting for Image</button> |
|
<button type="button" id="reset-button" class="button" disabled="disabled" name="reset" onclick="fullReset()">Reset</button> |
|
</div> |
|
</div> |
|
|
|
<div> |
|
<div id="drop-area"> |
|
<form class="my-form" name="upload_images"> |
|
<p>Upload image by dragging and dropping images onto the dashed region</p> |
|
<input type="file" id="fileElem" accept="image/*" onchange="handleFiles(this.files)"> |
|
<label class="btn" for="fileElem">Select some files</label> |
|
</form> |
|
<progress id="progress-bar" max=100 value=0 style="width:100%"></progress> |
|
<div id="gallery"></div> |
|
</div> |
|
</div> |
|
|
|
</div> |
|
</div> |
|
|
|
|
|
|
|
<script type="text/javascript"> |
|
|
|
var task_id = "" |
|
var task_status = "" |
|
|
|
|
|
|
|
|
|
let dropArea = document.getElementById("drop-area") |
|
|
|
|
|
;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { |
|
dropArea.addEventListener(eventName, preventDefaults, false) |
|
document.body.addEventListener(eventName, preventDefaults, false) |
|
}) |
|
|
|
|
|
;['dragenter', 'dragover'].forEach(eventName => { |
|
dropArea.addEventListener(eventName, highlight, false) |
|
}) |
|
|
|
;['dragleave', 'drop'].forEach(eventName => { |
|
dropArea.addEventListener(eventName, unhighlight, false) |
|
}) |
|
|
|
|
|
dropArea.addEventListener('drop', handleDrop, false) |
|
|
|
function preventDefaults (e) { |
|
e.preventDefault() |
|
e.stopPropagation() |
|
} |
|
|
|
function highlight(e) { |
|
dropArea.classList.add('highlight') |
|
} |
|
|
|
function unhighlight(e) { |
|
dropArea.classList.remove('active') |
|
} |
|
|
|
function handleDrop(e) { |
|
var dt = e.dataTransfer |
|
var files = dt.files |
|
|
|
handleFiles(files) |
|
} |
|
|
|
let uploadProgress = [] |
|
let progressBar = document.getElementById('progress-bar') |
|
|
|
function initializeProgress(numFiles) { |
|
progressBar.value = 0 |
|
uploadProgress = [] |
|
|
|
for(let i = numFiles; i > 0; i--) { |
|
uploadProgress.push(0) |
|
} |
|
} |
|
|
|
function updateProgress(fileNumber, percent) { |
|
uploadProgress[fileNumber] = percent |
|
let total = uploadProgress.reduce((tot, curr) => tot + curr, 0) / uploadProgress.length |
|
progressBar.value = total |
|
} |
|
|
|
function handleFiles(files) { |
|
files = [...files] |
|
initializeProgress(files.length) |
|
files.forEach(uploadFile) |
|
files.forEach(previewFile) |
|
} |
|
|
|
function previewFile(file) { |
|
let reader = new FileReader() |
|
reader.readAsDataURL(file) |
|
reader.onloadend = function() { |
|
let img = document.createElement('img') |
|
img.src = reader.result |
|
img.classList.add('no-drag-select') |
|
document.getElementById('gallery').appendChild(img) |
|
} |
|
} |
|
|
|
let submitButton = document.getElementById("submit-button") |
|
let resetButton = document.getElementById("reset-button") |
|
|
|
function fullReset() { |
|
var url = '/cancel-manual-request' |
|
var xhr = new XMLHttpRequest() |
|
xhr.open('POST', url, true) |
|
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8") |
|
|
|
xhr.addEventListener('readystatechange', function (e) { |
|
if (xhr.readyState == 4 && xhr.status == 200) { |
|
reset() |
|
} |
|
}) |
|
xhr.send(JSON.stringify({ |
|
"task_id": task_id, |
|
})) |
|
} |
|
|
|
function reset() { |
|
var s_area = document.getElementById('s-area') |
|
for (var i = s_area.children.length - 1; i >= 0; --i) { |
|
var child = s_area.children[i] |
|
if (child.tagName == "INPUT") { |
|
child.remove() |
|
} |
|
} |
|
var t_area = document.getElementById('t-area') |
|
for (var i = t_area.children.length - 1; i >= 0; --i) { |
|
var child = t_area.children[i] |
|
if (child.tagName == "INPUT") { |
|
child.remove() |
|
} |
|
} |
|
|
|
progressBar.value = 0 |
|
submitButton.innerHTML = "Waiting for Image" |
|
submitButton.onclick = null |
|
submitButton.setAttribute("disabled", "disabled") |
|
|
|
resetButton.innerHTML = "No Image" |
|
resetButton.onclick = fullReset |
|
resetButton.setAttribute("disabled", "disabled") |
|
|
|
var img = document.getElementsByTagName("img")[0] |
|
img.remove() |
|
} |
|
|
|
function downloadImageAndReset(path) { |
|
const url = "/result-type" |
|
const xhr = new XMLHttpRequest() |
|
xhr.open('GET', url, true) |
|
xhr.addEventListener('readystatechange', function (e) { |
|
if (xhr.readyState == 4 && xhr.status == 200) { |
|
|
|
|
|
const a = document.createElement('a') |
|
a.href = path |
|
a.download = "result."+xhr.responseText |
|
document.body.appendChild(a) |
|
a.click() |
|
document.body.removeChild(a) |
|
|
|
reset() |
|
} |
|
}) |
|
xhr.send(null) |
|
|
|
} |
|
|
|
function uploadFile(file, i) { |
|
|
|
|
|
submitButton.setAttribute("disabled", "disabled") |
|
submitButton.innerHTML = "Uploading" |
|
|
|
resetButton.innerHTML = "Waiting" |
|
resetButton.setAttribute("disabled", "disabled") |
|
|
|
|
|
var url = '/manual-translate' |
|
var xhr = new XMLHttpRequest() |
|
var formData = new FormData() |
|
xhr.open('POST', url, true) |
|
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest') |
|
|
|
|
|
xhr.upload.addEventListener("progress", function(e) { |
|
updateProgress(i, (e.loaded * 100.0 / e.total) || 100) |
|
if (e.loaded == e.total) |
|
submitButton.innerHTML = "Processing" |
|
}) |
|
|
|
xhr.addEventListener('readystatechange', function(e) { |
|
if (xhr.readyState == 4 && xhr.status == 200) { |
|
updateProgress(i, 100) |
|
|
|
const obj = JSON.parse(xhr.response) |
|
console.log(obj) |
|
|
|
task_id = obj.task_id |
|
task_status = obj.status |
|
|
|
var sArea = document.getElementById('s-area') |
|
var tArea = document.getElementById('t-area') |
|
|
|
for (var i = 0; obj.trans_result != null && i < obj.trans_result.length; i++) { |
|
var input_s = document.createElement("input") |
|
var input_t = document.createElement("input") |
|
|
|
input_s.value = obj.trans_result[i].s |
|
input_t.value = obj.trans_result[i].t |
|
|
|
sArea.appendChild(input_s) |
|
tArea.appendChild(input_t) |
|
|
|
|
|
} |
|
|
|
submitButton.removeAttribute("disabled") |
|
submitButton.innerHTML = "Submit" |
|
submitButton.onclick = submit |
|
|
|
resetButton.removeAttribute("disabled") |
|
resetButton.innerHTML = "Reset" |
|
} |
|
else if (xhr.readyState == 4 && xhr.status != 200) { |
|
|
|
alert("upload failed for "+file.name) |
|
} |
|
}) |
|
|
|
|
|
|
|
formData.append('file', file) |
|
xhr.send(formData) |
|
} |
|
|
|
function submit() { |
|
|
|
submitButton.setAttribute("disabled", "disabled") |
|
submitButton.innerHTML = "Running" |
|
|
|
resetButton.setAttribute("disabled", "disabled") |
|
resetButton.innerHTML = "Waiting" |
|
|
|
var inputs = document.getElementsByTagName("input") |
|
|
|
var trans_result = [] |
|
var j = ((inputs.length-2)/2)+1 |
|
var k = 0 |
|
|
|
for (var i = 1; i<=((inputs.length-2)/2); i++) { |
|
|
|
trans_result[k] = { |
|
's' : inputs[i].value, |
|
't' : inputs[j].value |
|
} |
|
|
|
j++ |
|
k++ |
|
} |
|
|
|
var postData = { |
|
"task_id": task_id, |
|
"status": task_status, |
|
"trans_result": trans_result |
|
} |
|
|
|
postData = JSON.stringify(postData) |
|
|
|
var url = '/post-manual-result' |
|
var xhr = new XMLHttpRequest() |
|
xhr.open('POST', url, true) |
|
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8") |
|
|
|
xhr.addEventListener('readystatechange', function(e) { |
|
if (xhr.readyState == 4 && xhr.status == 200) { |
|
var img = document.getElementsByTagName("img")[0] |
|
img.src = "/result/" + task_id |
|
img.onclick = (function (task_id) { |
|
return function () { |
|
downloadImageAndReset("/result/" + task_id) |
|
}; |
|
})(task_id) |
|
} |
|
else if (xhr.readyState == 4 && xhr.status != 200) { |
|
|
|
alert("Request failed!") |
|
} |
|
submitButton.removeAttribute("disabled") |
|
submitButton.innerHTML = "Download Image" |
|
submitButton.onclick = (function(task_id) { return function() { |
|
downloadImageAndReset("/result/" + task_id) |
|
};})(task_id) |
|
|
|
resetButton.removeAttribute("disabled") |
|
resetButton.innerHTML = "Reset" |
|
resetButton.onclick = reset |
|
|
|
}) |
|
|
|
|
|
xhr.send(postData) |
|
|
|
|
|
} |
|
</script> |
|
</body> |
|
</html> |