What I want the user to do, in this order:
- Select a photo using a file input.
- See a notification that the image is being compressed.
- See the compressed photo in the grey div.
What the problem is:
The selected photo doesn't appear, the div remains grey. This happens only in Firefox (50.0.2), but not always. It seems like the bigger the photo (e.g. 18 MB) and the more I move the mouse during compression, the more likely it is to happen. (Not sure, till testing.)
document.addEventListener('change', function(event) {
if (event.target.files && event.target.files[0]) {
toast('One moment please, the photo is being compressed...', true);
var reader = new FileReader();
reader.onload = function(event) {
var r = event.target.result;
setTimeout(function() {
compress(r, function(compressed) {
document.querySelector('#image').style.backgroundImage = 'url(' + compressed + ')';
clearToast();
});
}, 10);
}
reader.readAsDataURL(event.target.files[0]);
}
});
function compress(source_img_obj, callback, maxWidth, quality, output_format) {
var tmp = new Image();
tmp.src = source_img_obj;
var source_img_obj = tmp;
var maxWidth = maxWidth || 1123;
var mime_type = (typeof output_format !== 'undefined' && output_format == 'png') ? 'image/png' : 'image/jpeg';
var natW = source_img_obj.naturalWidth;
var natH = source_img_obj.naturalHeight;
var quality = quality || 60;
var ratio = natH / natW;
if (natW > maxWidth) {
natW = maxWidth;
natH = ratio * maxWidth;
}
var cvs = document.createElement('canvas');
cvs.width = natW;
cvs.height = natH;
var ctx = cvs.getContext('2d').drawImage(source_img_obj, 0, 0, natW, natH);
var result = cvs.toDataURL(mime_type, quality / 100);
if (typeof callback == 'function') callback(result);
return result;
};
function toast(txt, sticky) {
window.toastSticky = (typeof sticky != 'boolean' ? false : sticky);
var t = document.querySelector('header p');
if (!t.classList.contains('toast')) {
window.toastOriginalText = t.innerHTML;
t.innerHTML = '';
t.classList.add('toast');
}
t.innerHTML = txt;
if (typeof sticky === 'undefined' || !sticky) {
window.toastTimeouts = (window.toastTimeouts || 0) + 1;
setTimeout(function() {
clearToast(true);
}, 2000);
}
};
function clearToast(isTimeout) {
var isTimeout = (typeof isTimeout != 'boolean' ? false : isTimeout);
if (isTimeout) window.toastTimeouts--;
var t = document.querySelector('header p');
if (t.classList.contains('toast') && !(isTimeout && (window.toastTimeouts > 0 || window.toastSticky))) {
t.innerHTML = '';
t.classList.remove('toast');
t.innerHTML = window.toastOriginalText;
}
};
#image {
background: grey;
background-size: cover;
height: 200px;
margin: 10px;
width: 200px;
}
<header>
<p>Please upload an image.</p>
</header>
<input type="file" accept="image/*">
<div id="image"></div>