Files
deskhub/DeskHub-Webseite/assets/js/upload-compress.js
T
2026-10-24 20:14:51 +00:00

79 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Verkleinert große Fotos, bevor sie hochgeladen werden (Handy-Fotos haben oft 5–15 MB).
* Das macht den Upload deutlich schneller. Ist etwas nicht möglich, wird die Originaldatei unverändert hochgeladen.
* Gilt für alle <input type="file"> auf der Seite; nur JPG/PNG über 1 MB, längste Seite höchstens 2400 px.
*/
(function () {
var MAX_SIDE = 2400, MIN_BYTES = 1024 * 1024, QUALITY = 0.82;
if (!window.DataTransfer || !window.HTMLCanvasElement || !window.URL) return;
function note(input, text) {
var el = input.parentNode && input.parentNode.querySelector('.upload-note');
if (!el) {
el = document.createElement('div');
el.className = 'upload-note';
el.style.cssText = 'font-size:.8rem;color:#64748b;margin-top:4px';
input.insertAdjacentElement('afterend', el);
}
el.textContent = text;
}
function shrink(file) {
return new Promise(function (resolve) {
if (!/^image\/(jpeg|png)$/.test(file.type) || file.size < MIN_BYTES) return resolve(file);
var url = URL.createObjectURL(file), img = new Image();
img.onerror = function () { URL.revokeObjectURL(url); resolve(file); };
img.onload = function () {
URL.revokeObjectURL(url);
var w = img.naturalWidth, h = img.naturalHeight, k = Math.min(1, MAX_SIDE / Math.max(w, h));
var c = document.createElement('canvas');
c.width = Math.round(w * k); c.height = Math.round(h * k);
var ctx = c.getContext('2d');
if (!ctx) return resolve(file);
ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, c.width, c.height);
ctx.drawImage(img, 0, 0, c.width, c.height);
c.toBlob(function (blob) {
if (!blob || blob.size >= file.size) return resolve(file);
var name = file.name.replace(/\.(png|jpe?g)$/i, '') + '.jpg';
resolve(new File([blob], name, { type: 'image/jpeg', lastModified: file.lastModified }));
}, 'image/jpeg', QUALITY);
};
img.src = url;
});
}
document.addEventListener('change', function (e) {
var input = e.target;
if (!input || input.type !== 'file' || input.dataset.shrunk === '1' || !input.files || !input.files.length) return;
var files = Array.prototype.slice.call(input.files);
if (!files.some(function (f) { return /^image\/(jpeg|png)$/.test(f.type) && f.size >= MIN_BYTES; })) return;
note(input, 'Bilder werden für einen schnelleren Upload verkleinert …');
Promise.all(files.map(shrink)).then(function (out) {
try {
var dt = new DataTransfer();
out.forEach(function (f) { dt.items.add(f); });
input.dataset.shrunk = '1';
input.files = dt.files;
input.dispatchEvent(new Event('change', { bubbles: true }));
input.dataset.shrunk = '';
var before = files.reduce(function (s, f) { return s + f.size; }, 0), after = out.reduce(function (s, f) { return s + f.size; }, 0);
note(input, after < before ? 'Bilder verkleinert: ' + (before / 1048576).toFixed(1) + ' MB → ' + (after / 1048576).toFixed(1) + ' MB' : '');
} catch (err) { note(input, ''); }
});
}, true);
// Beim Absenden: Knopf sperren, damit nicht doppelt hochgeladen wird, und Fortschritt anzeigen
document.addEventListener('submit', function (e) {
var form = e.target;
if (!form || !form.querySelector || !form.querySelector('input[type=file]')) return;
var has = Array.prototype.some.call(form.querySelectorAll('input[type=file]'), function (i) { return i.files && i.files.length; });
if (!has) return;
setTimeout(function () {
if (e.defaultPrevented) return;
var b = form.querySelector('button[type=submit]');
if (b) { b.disabled = true; b.textContent = 'Wird hochgeladen …'; }
}, 0);
});
})();