var DocscanFiles = function ($) { 'use strict'; var me = { elem: {}, storage: { fileId: null, previewFileId: null, documentType: 'verbindlichkeit', dataTableSettings: {}, dragTimer: null, uploadData: [] }, selector: { filesTable: '#docscan_files', preview: '#preview-iframe', dialog: '#docscan-files-dialog', dialogTabs: '#filetabs', dialogContent: '#docscan-files-content', documentTableContainer: '.document-table-container', documentFilterCheckbox: '.document-filter-checkbox', documentAssignButton: '.document-assign-action', createLiabilityButton: '.create-liability-button', uploadDropzoneWrapper: '#dropzone-wrapper', uploadDropzone: '#dropzone' }, init: function () { me.elem.$docscanDialog = $(me.selector.dialog); me.elem.$previewIframe = $(me.selector.preview); me.elem.$dropzone = $(me.selector.uploadDropzone); me.elem.$dropzoneWrapper = $(me.selector.uploadDropzoneWrapper); me.initDialog(); me.attachEvents(); }, /** * Benötigte Events attachen */ attachEvents: function () { // Tabellenzeile wird angeklickt $(document).on('click', 'table#docscan_files tr', function () { me.onClickFileTableRow(this); }); // Hinzufügen-Button wird angeklickt $(document).on('click', 'table#docscan_files .docscan-add-button', function (e) { e.stopPropagation(); // Blockt Click-Event auf Tabellenzeile e.preventDefault(); me.onClickAddButton(this); }); // Löschen-Button wird angeklickt $(document).on('click', 'table#docscan_files .docscan-delete-button', function (e) { e.stopPropagation(); // Blockt Click-Event auf Tabellenzeile e.preventDefault(); me.onClickDeleteButton(this); }); // Im Dialog-Modal wird der Tab gewechselt $(document).on('tabsactivate', me.selector.dialogTabs, function (event, ui) { me.onChangeFileTab(ui.newTab, ui.oldTab); }); // "Datei zuweisen"-Button wurde in UI-Dialog-Table angeklickt $(document).on('click', me.selector.documentAssignButton, function (e) { e.preventDefault(); me.onClickDocumentAssignButton(this); }); // DataTable-Filter wird geändert $(document).on('change', me.selector.documentFilterCheckbox, function () { me.onChangeTableFilter(this); }); // Neue Verbindlichkeit anlegen $(document).on('click', me.selector.createLiabilityButton, function () { me.createNewLiability(); }); // Dropzone einblenden $(document).on('dragover', function (e) { var dt = e.originalEvent.dataTransfer; if (typeof dt.types && dt.types.indexOf('Files') !== -1) { me.showDropzone(); window.clearTimeout(me.dragTimer); } }); // Dropzone ausblenden $(document).on('dragleave', function () { me.dragTimer = window.setTimeout(function () { if (me.storage.previewFileId !== null) { me.hideDropzone(); } }, 25); }); // Dateien werden in Dropzone gedropped me.elem.$dropzoneWrapper.on('drop', function (e) { e.preventDefault(); me.handleDroppedFiles(e.dataTransfer.files); me.elem.$dropzone.css('borderColor', '#CCC'); }); // Dropzone: Rahmenfarbe ändern bei Drag me.elem.$dropzoneWrapper .on('dragover', function (e) { e.preventDefault(); me.elem.$dropzone.css('borderColor', 'darkred'); }) .on('dragleave', function () { me.elem.$dropzone.css('borderColor', '#CCC'); }); }, /** * DataTable-Filter wurde geändert * * @param {HTMLElement} element */ onChangeTableFilter: function (element) { var isActive = $(element).prop('checked'); var filterColumn = $(element).data('filter-column'); if (typeof isActive === 'undefined' || typeof filterColumn === 'undefined') { return; } // Prüfen ob DataTable vorhanden if (!$.fn.DataTable.isDataTable(me.elem.$currentDataTable)) { return; } var dataTable = me.elem.$currentDataTable.DataTable(); // Filter anwenden if (isActive) { dataTable.column(filterColumn).search('true', false, false, false).draw(); } else { dataTable.column(filterColumn).search('', false, false, false).draw(); } }, /** * Tabellenzeile wird angeklickt * * @param {HTMLElement} element Angeklickte Tabellenzeile */ onClickFileTableRow: function (element) { // Datei-ID aus Hinzufügen-Button lesen var $docscanDataItem = $(element).find('.docscan-add-button'); var fileId = parseInt($docscanDataItem.data('file')); if (isNaN(fileId) || fileId === 0) { return; } // Passende Datei-Vorschau wird bereits angezeigt if (me.storage.previewFileId === fileId) { return; } // Dateivorschau anzeigen me.previewFileInIframe(fileId); }, /** * @param {HTMLElement} element */ onClickAddButton: function (element) { var $element = $(element); var fileId = parseInt($element.data('file')); if (isNaN(fileId) || fileId === 0) { return; } // UI-Dialog anzeigen me.storage.fileId = fileId; me.displayDialog(); var fileType = $element.data('type'); if (fileType !== '' && fileType !== null) { var types = { 'verbindlichkeit': 'verbindlichkeit', 'kassenbuch': 'kasse', 'reisekosten': 'reisekosten', 'bestellung': 'bestellung', 'adresse': 'adressen' }; me.storage.documentType = types[fileType]; $(me.selector.dialogTabs).tabs('option', 'active', Object.keys(types).indexOf(fileType)); } }, /** * @param {HTMLElement} element */ onClickDeleteButton: function (element) { var fileId = parseInt($(element).data('file')); if (isNaN(fileId) || fileId === 0) { return; } var confirm = window.confirm('Möchten Sie die Datei wirklich löschen?'); if (confirm === false) { return; } // Datei löschen me.deleteFile(fileId); }, /** * Im UI-Dialog wird der Tab gewechselt * * @param {HTMLElement} newTab Tab-Element das aktiviert wird * @param {HTMLElement} oldTab Tab-Element das vorher aktiv war */ onChangeFileTab: function (newTab, oldTab) { var docTypeBefore = $(oldTab).data('type'); me.destroyDataTable(docTypeBefore); me.storage.documentType = $(newTab).data('type'); me.loadDataTable(); }, /** * "Datei zuweisen"-Button wurde angeklickt * * @param {HTMLElement} element Angeklickter Button */ onClickDocumentAssignButton: function (element) { var $tableRow = $(element).parents('tr'); if (!$.fn.DataTable.isDataTable(me.elem.$currentDataTable)) { alert('Unbekannter Fehler #1: DataTable konnte nicht gefunden werden.'); return; } var $dataTable = me.elem.$currentDataTable.DataTable(); var data = $dataTable.row($tableRow).data(); // ID aus DataTable-Datensatz holen var objectId = parseInt(data.id); if (isNaN(objectId)) { alert('Unbekannter Fehler #2: ID für Zuweisung konnte nicht gefunden werden.'); return; } // Datei-Stichwort zuweisen me.assignDocumentKeyword(me.storage.documentType, objectId); }, /** * Datei-Stichwort zuweisen * * @param {string} documentType * @param {number} objectId */ assignDocumentKeyword: function (documentType, objectId) { $.ajax({ url: 'index.php?module=docscan&action=edit&cmd=assign-file', data: {keyword: documentType, file: me.storage.fileId, object: objectId}, type: 'POST', dataType: 'json', success: function (result) { if (result.success === false) { alert('Unbekannter Fehler #3. Datei konnte nicht zugewiesen werden.'); } me.reloadFilesTable(); me.showDropzone(); me.closeDialog(); } }); }, /** * Dateivorschau anzeigen * * @param {number} fileId */ previewFileInIframe: function (fileId) { $.ajax({ url: 'index.php?module=docscan&action=preview&id=' + fileId, type: 'GET', dataType: 'json', success: function (data) { /** @namespace data.iframe_src */ if (typeof data.iframe_src === 'undefined') { alert('Unbekannter Fehler #4. Datei konnte nicht abgerufen werden.'); return; } // Dropzone ausblenden me.hideDropzone(); // IFrame-Inhalt ändern me.elem.$previewIframe.attr('src', data.iframe_src); // Merken welche Datei angezeigt wird me.storage.previewFileId = fileId; } }); }, /** * Datei löschen * * @param {number} fileId */ deleteFile: function (fileId) { $.ajax({ url: 'index.php?module=docscan&action=edit&cmd=delete-file', data: {file: fileId}, type: 'POST', dataType: 'json', success: function (data) { if (typeof data.success === 'undefined' || data.success === false) { if (data.hasOwnProperty('error')) { alert(data.error); } else { alert('Unbekannter Fehler #7. Datei konnte nicht gelöscht werden.'); } } me.reloadFilesTable(); me.showDropzone(); } }); }, /** * UI-Dialog initialisieren */ initDialog: function () { me.elem.$docscanDialog.dialog({ title: 'Datei-Zuordnung', modal: true, minWidth: 900, closeOnEscape: false, autoOpen: false, resizable: false }); // Tabs initialisieren $(me.selector.dialogTabs).tabs(); }, /** * UI-Dialog anzeigen (vorher DataTable laden) */ displayDialog: function () { me.loadDataTable().then(me.openDialog); }, /** * HTML-Template und DataTable-Einstellungen laden * * @return {Deferred} jQuery Promise Object */ loadDataTable: function () { return me.fetchDataTableHtmlTemplate() .then(me.fetchDataTableSettings) .then(me.initDataTable); }, /** * UI-Dialog öffnen */ openDialog: function () { window.setTimeout(function () { // Kurz warten bis DataTable aufgebaut ist, damit Höhe berechnet werden kann me.elem.$docscanDialog.dialog('open'); me.elem.$docscanDialog.dialog('option', 'height', 'auto'); }, 150); }, /** * UI-Dialog schließen */ closeDialog: function () { me.elem.$docscanDialog.dialog('close'); }, /** * DataTable mit Docscan-Dateien neuladen */ reloadFilesTable: function () { var $files = $(me.selector.filesTable); if ($.fn.DataTable.isDataTable($files)) { $files.DataTable().ajax.reload(null, false); // false = hold the current paging position } me.storage.previewFileId = null; }, /** * DataTable initialisieren */ initDataTable: function () { var $tabContent = me.elem.$docscanDialog.find('#' + me.storage.documentType + '-tab'); me.elem.$currentDataTable = $tabContent.find('table.display'); me.elem.$currentDataTable.css('width', '100%'); // DataTable ist bereist initialisiert > Instanz zerstören if ($.fn.DataTable.isDataTable(me.elem.$currentDataTable)) { me.elem.$currentDataTable.DataTable().destroy(); } // DataTable initialisieren var table = me.elem.$currentDataTable.DataTable(me.storage.dataTableSettings); table.on('init.dt', function () { $(me.selector.documentTableContainer).show(); }); }, /** * Zerstört eine DataTable-Instanz * * @param {string} docType */ destroyDataTable: function (docType) { var $tabContent = me.elem.$docscanDialog.find('#' + docType + '-tab'); var $table = $tabContent.find('table.display'); if ($.fn.DataTable.isDataTable($table)) { $table.DataTable().destroy(); me.elem.$currentDataTable = null; } }, /** * DataTable-HTML-Tabelle laden * * @return {jqXHR} jQuery jqXHR-Objekt */ fetchDataTableHtmlTemplate: function () { return $.ajax({ url: 'index.php?module=docscan&action=edit&cmd=table-html', data: {'type': me.storage.documentType, 'id': me.storage.fileId}, type: 'GET', dataType: 'html', success: function (data) { me.elem.$docscanDialog.find('#' + me.storage.documentType + '-tab').html(data); me.elem.$docscanDialog.find(me.selector.documentTableContainer).hide(); } }); }, /** * DataTable-Einstellungen laden * * @return {jqXHR|null} jQuery jqXHR-Objekt oder null wenn Modul nicht zur Verfügung steht */ fetchDataTableSettings: function () { var $tabContent = me.elem.$docscanDialog.find('#' + me.storage.documentType + '-tab'); var $disabledContainer = $tabContent.find('.module-disabled'); if ($disabledContainer.length > 0) { return null; // Manche Module stehen erst ab der Business-Version zur Verfügung } return $.ajax({ url: 'index.php?module=docscan&action=edit&cmd=table-settings', data: {'type': me.storage.documentType, 'id': me.storage.fileId}, type: 'GET', dataType: 'json', success: function (data) { me.storage.dataTableSettings = data; } }); }, /** * Neue Verbindlichkeit anlegen + Datei zuweisen * * Bei Erfolg wird die Verbindlichkeit geöffnet. */ createNewLiability: function () { $.ajax({ url: 'index.php?module=docscan&action=edit&cmd=create-liability', data: {'id': me.storage.fileId}, type: 'GET', dataType: 'json', success: function (data) { if (typeof data.success === 'undefined' || data.success === false) { alert('Unbekannter Fehler #5. Verbindlichkeit konnte nicht angelegt werden.'); return; } /** @namespace data.liability */ if (typeof data.liability === 'undefined') { alert('Unbekannter Fehler #6. Verbindlichkeit konnte nicht angelegt werden.'); return; } window.location.href = './index.php?module=verbindlichkeit&action=edit&id=' + data.liability; } }); }, /** * @param {FileList} files */ handleDroppedFiles: function (files) { $.each(files, function (index, file) { // Dateien einlesen var fileReader = new FileReader(); fileReader.onload = (function (file) { return function () { if (file.size === 0 || file.type === '') { return; } var isImage = file.type.substr(0, 6) === 'image/'; var isPdf = file.type === 'application/pdf'; if (!isImage && !isPdf) { alert('Dieser Dateityp wird nicht unterstützt. Bitte laden Sie nur PDFs und Bilder hoch.'); return; } // Datei einzeln hochladen me.uploadDroppedFiles(file.name, this.result); }; })(files[index]); fileReader.readAsDataURL(file); }); }, /** * In Dropzone abgelegte Datei hochladen * * @param {string} name Dateiname * @param {string} data Uploaddaten (base64-kodiert) */ uploadDroppedFiles: function (name, data) { if (typeof name === 'undefined' || typeof data === 'undefined') { return; } $.ajax({ type: 'POST', url: 'index.php?module=docscan&action=list&cmd=drop-file', data: {name: name, data: data}, dataType: 'json', success: function (result) { if (result && result.success && result.success === true) { me.debounce(function () { // DataTable aktualisieren me.reloadFilesTable(); // Vorschau zur zuletzt hochgeladenen Datei in IFrame anzeigen if (typeof result.file !== 'undefined') { me.previewFileInIframe(result.file); } }, 250); } } }); }, /** * Dropzone anzeigen (Vorschau ausblenden) */ showDropzone: function () { me.elem.$dropzone.addClass('active'); }, /** * Dropzone ausblenden (Vorschau anzeigen) */ hideDropzone: function () { me.elem.$dropzone.removeClass('active'); }, /** * Puffer-Funktion um Events erst nach einer bestimmten Zeit auszuführen * * @param {function} callback * @param {number} delay */ debounce: function (callback, delay) { var context = this; var args = arguments; window.clearTimeout(me.storage.buffer); me.storage.buffer = window.setTimeout(function () { callback.apply(context, args); }, delay || 250); } }; return { init: me.init }; }(jQuery); $(document).ready(function () { if ($('#docscan-module').length === 0) { return; } DocscanFiles.init(); });