// Sunfish: mejora de la subida en el modo moderno (solo se incluye en navegadores actuales).
// Sin este script el formulario funciona igual; con el, se puede arrastrar ficheros a la pagina,
// se ve el progreso y los ficheros grandes se envian por trozos con PUT + Content-Range.
(function () {
'use strict';
var form = document.getElementById('sf-upload');
if (!form || !window.XMLHttpRequest || !window.File || !File.prototype.slice) return;
var input = form.querySelector('input[type=file]');
var status = document.getElementById('sf-status');
var uploadingText = form.getAttribute('data-uploading') || 'Uploading';
var doneText = form.getAttribute('data-done') || 'Done';
var CHUNK = 1024 * 1024;
var busy = false;
function newId() {
var s = '';
for (var i = 0; i < 24; i++) s += Math.floor(Math.random() * 16).toString(16);
return s;
}
function show(text) { if (status) status.textContent = text; }
function sendFile(file, progress, done) {
var id = newId();
var url = location.pathname + encodeURIComponent(file.name);
function part(offset) {
var end = Math.min(offset + CHUNK, file.size);
var xhr = new XMLHttpRequest();
xhr.open('PUT', url);
xhr.setRequestHeader('X-Sunfish-Upload', id);
if (file.size > 0)
xhr.setRequestHeader('Content-Range', 'bytes ' + offset + '-' + (end - 1) + '/' + file.size);
xhr.upload.onprogress = function (e) { progress(offset + e.loaded); };
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
if (end >= file.size) done(null); else part(end);
} else {
done(file.name + ': ' + (xhr.responseText || xhr.status));
}
};
xhr.onerror = function () { done(file.name + ': network error'); };
xhr.send(file.slice(offset, end));
}
part(0);
}
function upload(fileList) {
if (busy || !fileList || !fileList.length) return;
busy = true;
var files = [], total = 0, sent = 0;
for (var i = 0; i < fileList.length; i++) { files.push(fileList[i]); total += fileList[i].size; }
function next(k) {
if (k >= files.length) {
show(doneText);
location.reload();
return;
}
var file = files[k];
sendFile(file, function (bytes) {
var pct = total > 0 ? Math.floor((sent + bytes) * 100 / total) : 100;
show(uploadingText + ' ' + file.name + '... ' + pct + '%');
}, function (error) {
if (error) { show(error); busy = false; return; }
sent += file.size;
next(k + 1);
});
}
next(0);
}
form.addEventListener('submit', function (e) {
if (!input || !input.files || !input.files.length) return;
e.preventDefault();
upload(input.files);
});
var body = document.body;
body.addEventListener('dragover', function (e) {
e.preventDefault();
body.className = 'sf-drop';
});
body.addEventListener('dragleave', function (e) {
if (e.target === body || !e.relatedTarget) body.className = '';
});
body.addEventListener('drop', function (e) {
e.preventDefault();
body.className = '';
if (e.dataTransfer) upload(e.dataTransfer.files);
});
})();