Files
ACORE/static/assets/js/documents.js
T

245 lines
9.8 KiB
JavaScript

(function () {
document.documentElement.classList.remove('oo-open');
var emptyLabel = 'или перетащите сюда / в список';
function dropRoot(el) {
return el && el.closest ? el.closest('.nc-drop') : null;
}
function browserDropRoot(el) {
return el && el.closest ? el.closest('.nc-browser-drop[data-nc-upload="1"]') : null;
}
function findUploadForm(fromEl) {
var browser = browserDropRoot(fromEl);
if (browser) {
var f = browser.querySelector('form.nc-drop');
if (f) return f;
}
return dropRoot(fromEl);
}
function uploadFilesViaForm(form, fileList) {
if (!form || !fileList || !fileList.length) return;
var files = Array.prototype.slice.call(fileList);
var url = form.getAttribute('hx-post') || form.getAttribute('action');
var targetSel = form.getAttribute('hx-target') || '#documents-browser';
var swap = form.getAttribute('hx-swap') || 'innerHTML';
function next() {
if (!files.length) return;
var file = files.shift();
var fd = new FormData(form);
fd.set('file', file, file.name);
fetch(url, {
method: 'POST',
body: fd,
credentials: 'same-origin',
headers: { 'HX-Request': 'true' },
}).then(function (r) {
return r.text().then(function (html) {
var target = document.querySelector(targetSel);
if (target) {
if (typeof htmx !== 'undefined' && htmx.swap) {
htmx.swap(target, html, { swapStyle: swap });
} else {
target.innerHTML = html;
}
// после swap форма пересоздана — продолжаем очередь
form = target.querySelector('form.nc-drop') || form;
}
if (files.length) next();
});
}).catch(function () { /* ignore */ });
}
next();
}
document.addEventListener('change', function (e) {
if (!e.target || !e.target.classList.contains('nc-drop-input')) return;
var drop = dropRoot(e.target);
var nameEl = drop && drop.querySelector('.nc-drop-name');
if (!nameEl) return;
var files = e.target.files;
if (!files || !files.length) {
nameEl.textContent = emptyLabel;
return;
}
nameEl.textContent = files.length === 1
? files[0].name
: (files.length + ' файлов');
});
document.addEventListener('dragover', function (e) {
var zone = browserDropRoot(e.target) || dropRoot(e.target);
if (!zone) return;
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
zone.classList.add('is-drag');
});
document.addEventListener('dragleave', function (e) {
var zone = browserDropRoot(e.target) || dropRoot(e.target);
if (!zone) return;
if (e.relatedTarget && zone.contains(e.relatedTarget)) return;
zone.classList.remove('is-drag');
});
document.addEventListener('drop', function (e) {
var browser = browserDropRoot(e.target);
var drop = dropRoot(e.target);
var zone = browser || drop;
if (!zone) return;
e.preventDefault();
zone.classList.remove('is-drag');
if (!e.dataTransfer || !e.dataTransfer.files.length) return;
var form = findUploadForm(e.target);
if (!form) return;
// автозагрузка сразу (без кнопки «Загрузить»)
uploadFilesViaForm(form, e.dataTransfer.files);
});
// Несколько файлов через кнопку «Загрузить» — по одному, как при DnD
document.addEventListener('submit', function (e) {
var form = e.target;
if (!form || !form.classList || !form.classList.contains('nc-drop')) return;
var input = form.querySelector('.nc-drop-input');
if (!input || !input.files || input.files.length <= 1) return;
e.preventDefault();
uploadFilesViaForm(form, input.files);
}, true);
document.addEventListener('htmx:afterSwap', function (e) {
if (!e.detail || !e.detail.target || e.detail.target.id !== 'main-content') return;
document.documentElement.classList.remove('oo-open');
});
// ── Модальный предпросмотр PDF / изображений ───────────────────────────
function ensurePreviewModal() {
var existing = document.getElementById('doc-preview-modal');
if (existing) return existing;
var overlay = document.createElement('div');
overlay.id = 'doc-preview-overlay';
overlay.className = 'doc-preview-overlay';
overlay.style.display = 'none';
overlay.addEventListener('click', docPreviewClose);
var modal = document.createElement('div');
modal.id = 'doc-preview-modal';
modal.className = 'doc-preview-modal';
modal.setAttribute('role', 'dialog');
modal.setAttribute('aria-modal', 'true');
modal.style.display = 'none';
modal.addEventListener('click', docPreviewClose);
modal.innerHTML =
'<div class="doc-preview-dialog" onclick="event.stopPropagation()">' +
' <div class="doc-preview-dialog-bar">' +
' <div class="doc-preview-dialog-title" id="doc-preview-title"></div>' +
' <div class="doc-preview-dialog-actions">' +
' <a id="doc-preview-download" class="btn btn-ghost" style="font-size:0.8125rem;" download>Скачать</a>' +
' <a id="doc-preview-full" class="btn btn-ghost" style="font-size:0.8125rem;" target="_blank" rel="noopener">На всю страницу</a>' +
' <button type="button" class="btn btn-ghost btn-icon" id="doc-preview-close" aria-label="Закрыть">✕</button>' +
' </div>' +
' </div>' +
' <div class="doc-preview-dialog-body" id="doc-preview-body"></div>' +
'</div>';
document.body.appendChild(overlay);
document.body.appendChild(modal);
document.getElementById('doc-preview-close').addEventListener('click', docPreviewClose);
return modal;
}
function downloadUrlFromInline(url) {
try {
var u = new URL(url, window.location.origin);
u.searchParams.delete('inline');
return u.pathname + u.search;
} catch (err) {
return String(url || '').replace(/([?&])inline=1(&|$)/, function (_, a, b) {
return a === '?' && b === '&' ? '?' : (b === '&' ? a : '');
});
}
}
window.docPreviewOpen = function (elOrUrl, title, kind) {
var url, name, previewKind;
if (typeof elOrUrl === 'string') {
url = elOrUrl;
name = title || '';
previewKind = kind || 'image';
} else if (elOrUrl && elOrUrl.getAttribute) {
url = elOrUrl.getAttribute('href') || '';
name = elOrUrl.getAttribute('data-doc-title') || elOrUrl.textContent || '';
previewKind = elOrUrl.getAttribute('data-doc-kind') || 'image';
} else {
return false;
}
if (!url) return false;
ensurePreviewModal();
var overlay = document.getElementById('doc-preview-overlay');
var modal = document.getElementById('doc-preview-modal');
var body = document.getElementById('doc-preview-body');
var titleEl = document.getElementById('doc-preview-title');
var dl = document.getElementById('doc-preview-download');
var full = document.getElementById('doc-preview-full');
if (titleEl) {
titleEl.textContent = name;
titleEl.title = name;
}
if (dl) {
dl.href = downloadUrlFromInline(url);
dl.setAttribute('download', name || '');
}
if (full) {
var fullHref = (elOrUrl && elOrUrl.getAttribute && elOrUrl.getAttribute('data-doc-full')) || url;
full.href = fullHref;
}
body.innerHTML = '';
if (previewKind === 'pdf') {
var frame = document.createElement('iframe');
frame.className = 'doc-preview-dialog-frame';
frame.title = name || 'PDF';
frame.src = url;
body.appendChild(frame);
} else {
var wrap = document.createElement('div');
wrap.className = 'doc-preview-dialog-image-wrap';
var img = document.createElement('img');
img.className = 'doc-preview-dialog-image';
img.alt = name || '';
img.src = url;
wrap.appendChild(img);
body.appendChild(wrap);
}
overlay.style.display = 'block';
modal.style.display = 'flex';
document.body.style.overflow = 'hidden';
return false;
};
window.docPreviewClose = function () {
var overlay = document.getElementById('doc-preview-overlay');
var modal = document.getElementById('doc-preview-modal');
var body = document.getElementById('doc-preview-body');
if (overlay) overlay.style.display = 'none';
if (modal) modal.style.display = 'none';
if (body) body.innerHTML = '';
document.body.style.overflow = '';
};
document.addEventListener('keydown', function (ev) {
if (ev.key !== 'Escape') return;
var modal = document.getElementById('doc-preview-modal');
if (modal && modal.style.display === 'flex') docPreviewClose();
});
})();