334 lines
12 KiB
JavaScript
334 lines
12 KiB
JavaScript
/*
|
|
$Revision$
|
|
$Id$
|
|
|
|
File: attachments.js
|
|
Description: clientside functions for attachments
|
|
Note: Wordt nog alleen voor PDA gebruikt
|
|
Een bestand wordt na kiezen altijd direct geupload en
|
|
dan krijgen we een token terug welke we uiteindelijk
|
|
submitten
|
|
|
|
Er zit ook drag-and-drop code in die we (nog) niet gebruiken
|
|
*/
|
|
|
|
async function resizeFile(file, inputEl)
|
|
{
|
|
var maxWidth = inputEl.getAttribute("data-max-default-width");
|
|
var maxHeight = inputEl.getAttribute("data-max-default-height");
|
|
// Verkleinen voor alle browsers behalve Internet Explorer.
|
|
var clientresize = (typeof createImageBitmap == "function" ? "1" : "0");
|
|
|
|
if (clientresize && maxWidth > 0 && maxHeight > 0)
|
|
{
|
|
var canvas = document.createElement('canvas');
|
|
const ctx = canvas.getContext('2d');
|
|
const img = await createImageBitmap(file);
|
|
if (img.width > maxWidth && img.height > maxHeight) // drempel voor verkleining van de afbeelding.
|
|
{
|
|
var ratio = Math.min(maxWidth / img.width, maxHeight / img.height);
|
|
var width = img.width * ratio + .5 | 0;
|
|
var height = img.height * ratio + .5 | 0;
|
|
// resize the canvas to the new dimensions
|
|
canvas.width = width;
|
|
canvas.height = height;
|
|
// scale & draw the image onto the canvas
|
|
ctx.drawImage(img, 0, 0, width, height);
|
|
// Get the binary (blob)
|
|
var blob = await new Promise(rs => canvas.toBlob(rs, "image/jpeg", 1));
|
|
var resizedFile = new File([blob], file.name, file);
|
|
return resizedFile;
|
|
}
|
|
else
|
|
return file;
|
|
}
|
|
else
|
|
return file;
|
|
}
|
|
|
|
function addFile(inputEl, file, eagerUpload) {
|
|
var attachmentsFields = $(inputEl).closest('.attachments_form').find('.attachments_fields');
|
|
var multi = $(inputEl).attr('multiple') == 'multiple'; // kenmerktype == [M]ap
|
|
var maxFiles = (multi ? 10 : 1);
|
|
|
|
if (attachmentsFields.children().length < maxFiles) {
|
|
var attachmentId = addFile.nextAttachmentId++;
|
|
var fileSpan = $('<span>', { id: 'attachments_' + attachmentId });
|
|
var param = $(inputEl).data('param');
|
|
if (!param) {param = 'attachments'};
|
|
var kval = $(inputEl).siblings("a[role=button]").attr("id"); // De 'Toevoegen' knop heeft de kval (bijv 'k123val') als id
|
|
if (!multi) { // kenmerktype != [M]ap
|
|
fileSpan.append(
|
|
$('<input>', { type: 'hidden', name: kval } ).val(file.name) // Dit veld is nodig voor kenmerktypes [E] & [F] om de bestandsnaam als kenmerkwaarde op te slaan
|
|
);
|
|
}
|
|
fileSpan.append(
|
|
$('<input>', { type: 'text',
|
|
class : 'icon icon-attachment filename readonly form-control-plaintext',
|
|
id: param + "_" + attachmentId + "_file",
|
|
name: param + '[' + attachmentId + '][filename]',
|
|
readonly: 'readonly'
|
|
} ).val(file.name),
|
|
$('<input>', { type: 'hidden', 'class': 'token', name: param + '[' + attachmentId + '][token]'} )
|
|
/* Gelijk een Delete knop invoegen is wat te complex */
|
|
).appendTo(attachmentsFields);
|
|
|
|
if(eagerUpload) {
|
|
ajaxUpload(file, attachmentId, fileSpan, inputEl);
|
|
}
|
|
|
|
return attachmentId;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
addFile.nextAttachmentId = 1;
|
|
|
|
function ajaxUpload(file, attachmentId, fileSpan, inputEl) {
|
|
|
|
function onLoadstart(e) {
|
|
fileSpan.removeClass('ajax-waiting');
|
|
fileSpan.addClass('ajax-loading');
|
|
$('input:submit', $(this).parents('form')).attr('disabled', 'disabled');
|
|
}
|
|
|
|
function onProgress(e) {
|
|
if(e.lengthComputable) {
|
|
this.progressbar( 'value', e.loaded * 100 / e.total );
|
|
}
|
|
}
|
|
|
|
async function actualUpload(file, attachmentId, fileSpan, inputEl)
|
|
{
|
|
ajaxUpload.uploading++;
|
|
// Bestanden verkleinen volgens de standaard formattering.
|
|
var resizedFile = await resizeFile(file, inputEl);
|
|
|
|
uploadBlob(resizedFile, $(inputEl).data('upload-path'), attachmentId, {
|
|
loadstartEventHandler: onLoadstart.bind(progressSpan),
|
|
progressEventHandler: onProgress.bind(progressSpan)
|
|
})
|
|
.done(function(result) {
|
|
if ("success" in result && !result.success)
|
|
{
|
|
FcltMgr.alert(result.message);
|
|
return;
|
|
}
|
|
addInlineAttachmentMarkup(resizedFile);
|
|
progressSpan.progressbar( 'value', 100 ).remove();
|
|
fileSpan.find('input.token').val(result.attachment.token);
|
|
|
|
// Bestandsnaam kan aangepast zijn. Bestandsnaam opnieuw zetten.
|
|
var param = $(inputEl).data('param');
|
|
var filename = param + "_" + attachmentId + "_file";
|
|
$("#" + filename).val(result.attachment.name);
|
|
})
|
|
.fail(function(result) {
|
|
progressSpan.text(result.statusText);
|
|
}).always(function() {
|
|
ajaxUpload.uploading--;
|
|
fileSpan.removeClass('ajax-loading');
|
|
var form = fileSpan.parents('form');
|
|
if (form.queue('upload').length == 0 && ajaxUpload.uploading == 0) {
|
|
$('input:submit', form).removeAttr('disabled');
|
|
}
|
|
form.dequeue('upload');
|
|
});
|
|
}
|
|
|
|
var progressSpan = $('<div>').insertAfter(fileSpan.find('input.filename'));
|
|
progressSpan.progressbar({
|
|
classes: {
|
|
"ui-progressbar": "highlight"
|
|
}
|
|
});
|
|
fileSpan.addClass('ajax-waiting');
|
|
|
|
var maxSyncUpload = 1; // || $(inputEl).data('max-concurrent-uploads');
|
|
|
|
if(maxSyncUpload == null || maxSyncUpload <= 0 || ajaxUpload.uploading < maxSyncUpload)
|
|
actualUpload(file, attachmentId, fileSpan, inputEl);
|
|
else
|
|
$(inputEl).parents('form').queue('upload', actualUpload.bind(this, file, attachmentId, fileSpan, inputEl));
|
|
}
|
|
|
|
ajaxUpload.uploading = 0;
|
|
|
|
function removeFile() {
|
|
$(this).closest('.attachments_form').find('.add_attachment').show();
|
|
$(this).parent('span').remove();
|
|
return false;
|
|
}
|
|
|
|
function uploadBlob(blob, uploadUrl, attachmentId, options) {
|
|
|
|
var actualOptions = $.extend({
|
|
loadstartEventHandler: $.noop,
|
|
progressEventHandler: $.noop
|
|
}, options);
|
|
|
|
uploadUrl = uploadUrl + encodeURIComponent(blob.name) + '?attachment_id=' + attachmentId;
|
|
if (blob instanceof window.File) {
|
|
uploadUrl += '&content_type=' + encodeURIComponent(blob.type);
|
|
}
|
|
|
|
return $.ajax(uploadUrl, {
|
|
type: 'POST',
|
|
contentType: 'application/octet-stream',
|
|
beforeSend: function(jqXhr, settings) {
|
|
jqXhr.setRequestHeader('Accept', 'application/json');
|
|
|
|
jqXhr.setRequestHeader('X-CSRF-TOKEN', RVT_token );
|
|
|
|
// attach proper File object
|
|
settings.data = blob;
|
|
},
|
|
xhr: function() {
|
|
var xhr = $.ajaxSettings.xhr();
|
|
xhr.upload.onloadstart = actualOptions.loadstartEventHandler;
|
|
xhr.upload.onprogress = actualOptions.progressEventHandler;
|
|
return xhr;
|
|
},
|
|
data: blob,
|
|
cache: false,
|
|
processData: false
|
|
});
|
|
}
|
|
|
|
function addInputFiles(inputEl) {
|
|
//var attachmentsFields = $(inputEl).closest('.attachments_form').find('.attachments_fields');
|
|
var attachementDiv = $(inputEl).closest('.attachments_form');
|
|
var addAttachment = $(inputEl).closest('.attachments_form').find('.add_attachment');
|
|
var clearedFileInput = $(inputEl).clone().val('');
|
|
var sizeExceeded = false;
|
|
var param = $(inputEl).data('param');
|
|
if (!param) {param = 'attachments'};
|
|
|
|
if ($.ajaxSettings.xhr().upload && inputEl.files) {
|
|
// upload files using ajax
|
|
sizeExceeded = uploadAndAttachFiles(inputEl.files, inputEl);
|
|
$(inputEl).remove();
|
|
} else { // Volgens mij is deze tak niet meer nodig sinds IE10
|
|
// browser not supporting the file API, upload on form submission
|
|
var attachmentId;
|
|
var aFilename = inputEl.value.split(/\/|\\/);
|
|
attachmentId = addFile(inputEl, { name: aFilename[ aFilename.length - 1 ] }, false);
|
|
if (attachmentId) {
|
|
$(inputEl).attr({ name: param + '[' + attachmentId + '][file]', style: 'display:none;' }).appendTo('#attachments_' + attachmentId);
|
|
}
|
|
}
|
|
|
|
clearedFileInput.prependTo(addAttachment);
|
|
attachementDiv.trigger("create");
|
|
let $bijlageButton = addAttachment.find("[data-role=button][nBijlagen]");
|
|
if ($bijlageButton.length) {
|
|
$bijlageButton.attr("nBijlagen", parseInt($bijlageButton.attr("nBijlagen") || 0, 10) + inputEl.files.length);
|
|
}
|
|
}
|
|
|
|
function uploadAndAttachFiles(files, inputEl)
|
|
{
|
|
var maxFileSize = $(inputEl).data('max-file-size');
|
|
var maxFileSizeExceeded = $(inputEl).data('max-file-size-message');
|
|
|
|
var sizeExceeded = false;
|
|
$.each(files, function() {
|
|
if (this.size && maxFileSize != null && this.size > parseInt(maxFileSize)) {sizeExceeded=true;}
|
|
});
|
|
if (sizeExceeded) {
|
|
FcltMgr.alert(maxFileSizeExceeded);
|
|
} else {
|
|
$.each(files, function() {addFile(inputEl, this, true);});
|
|
}
|
|
return sizeExceeded;
|
|
}
|
|
|
|
function handleFileDropEvent(e) {
|
|
|
|
$(this).removeClass('fileover');
|
|
blockEventPropagation(e);
|
|
|
|
if ($.inArray('Files', e.dataTransfer.types) > -1) {
|
|
handleFileDropEvent.target = e.target;
|
|
uploadAndAttachFiles(e.dataTransfer.files, $('input:file.filedrop').first());
|
|
}
|
|
}
|
|
handleFileDropEvent.target = '';
|
|
|
|
function dragOverHandler(e) {
|
|
$(this).addClass('fileover');
|
|
blockEventPropagation(e);
|
|
}
|
|
|
|
function dragOutHandler(e) {
|
|
$(this).removeClass('fileover');
|
|
blockEventPropagation(e);
|
|
}
|
|
|
|
function setupFileDrop() {
|
|
if (window.File && window.FileList && window.ProgressEvent && window.FormData) {
|
|
|
|
// $.event.fixHooks.drop = { props: [ 'dataTransfer' ] };
|
|
|
|
$('form div.box:not(.filedroplistner)').has('input:file.filedrop').each(function() {
|
|
$(this).on({
|
|
dragover: dragOverHandler,
|
|
dragleave: dragOutHandler,
|
|
drop: handleFileDropEvent
|
|
}).addClass('filedroplistner');
|
|
});
|
|
}
|
|
}
|
|
|
|
function addInlineAttachmentMarkup(file) {
|
|
// insert uploaded image inline if dropped area is currently focused textarea
|
|
if($(handleFileDropEvent.target).hasClass('wiki-edit') && $.inArray(file.type, window.wikiImageMimeTypes) > -1) {
|
|
var $textarea = $(handleFileDropEvent.target);
|
|
var cursorPosition = $textarea.prop('selectionStart');
|
|
var description = $textarea.val();
|
|
var sanitizedFilename = file.name.replace(/[\/\?\%\*\:\|\"\'<>\n\r]+/, '_');
|
|
var inlineFilename = encodeURIComponent(sanitizedFilename);
|
|
var newLineBefore = true;
|
|
var newLineAfter = true;
|
|
if(cursorPosition === 0 || description.substr(cursorPosition-1,1).match(/\r|\n/)) {
|
|
newLineBefore = false;
|
|
}
|
|
if(description.substr(cursorPosition,1).match(/\r|\n/)) {
|
|
newLineAfter = false;
|
|
}
|
|
|
|
$textarea.val(
|
|
description.substring(0, cursorPosition)
|
|
+ (newLineBefore ? '\n' : '')
|
|
+ inlineFilename
|
|
+ (newLineAfter ? '\n' : '')
|
|
+ description.substring(cursorPosition, description.length)
|
|
);
|
|
|
|
$textarea.prop({
|
|
'selectionStart': cursorPosition + newLineBefore,
|
|
'selectionEnd': cursorPosition + inlineFilename.length + newLineBefore
|
|
});
|
|
$textarea.closest('.jstEditor')
|
|
.siblings('.jstElements')
|
|
.find('.jstb_img').click();
|
|
|
|
// move cursor into next line
|
|
cursorPosition = $textarea.prop('selectionStart');
|
|
$textarea.prop({
|
|
'selectionStart': cursorPosition + 1,
|
|
'selectionEnd': cursorPosition + 1
|
|
});
|
|
|
|
}
|
|
}
|
|
|
|
$(setupFileDrop);
|
|
|
|
$(function()
|
|
{
|
|
$("input.deleted_attachment").change(function(){
|
|
$(this).parents('.existing-attachment').toggleClass('deleted', $(this).is(":checked"));
|
|
}).change();
|
|
});
|