Files
ACORE/static/assets/js/directories.js
T
lokses ae54d93442 core: секции портала, контроль доступа и вью страниц
Section-based portal access, matrix прав по группам, аккаунтинг-портал,
управление группами пользователей, справочники, дашборд и общий каркас
навигации/стилей.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-09 18:03:20 +03:00

113 lines
3.8 KiB
JavaScript

/**
* Drag-and-drop порядка записей системных справочников.
* Перетаскивание только среди соседей (один parent_id).
*/
(function () {
'use strict';
var dragRow = null;
function csrfToken() {
var el = document.querySelector('#dir-items-tbody [name=csrfmiddlewaretoken], input[name=csrfmiddlewaretoken]');
if (el) return el.value;
var m = document.cookie.match(/(?:^|; )csrftoken=([^;]+)/);
return m ? decodeURIComponent(m[1]) : '';
}
function saveOrder(row) {
var tbody = document.getElementById('dir-items-tbody');
if (!tbody || !row) return;
var parentId = row.getAttribute('data-parent-id') || '';
var typeId = tbody.getAttribute('data-type-id');
var url = tbody.getAttribute('data-reorder-url');
if (!typeId || !url) return;
var ids = [];
tbody.querySelectorAll('tr.dir-item-row').forEach(function (tr) {
if ((tr.getAttribute('data-parent-id') || '') === parentId) {
ids.push(tr.getAttribute('data-id'));
}
});
if (!ids.length) return;
var form = document.createElement('form');
form.method = 'POST';
form.action = url;
form.style.display = 'none';
function add(name, value) {
var input = document.createElement('input');
input.type = 'hidden';
input.name = name;
input.value = value;
form.appendChild(input);
}
add('csrfmiddlewaretoken', csrfToken());
add('order', ids.join(','));
add('parent_id', parentId);
document.body.appendChild(form);
form.submit();
}
function onDragStart(e) {
var handle = e.target.closest('.dir-drag-handle');
if (!handle) {
e.preventDefault();
return;
}
var row = handle.closest('tr.dir-item-row');
if (!row) return;
dragRow = row;
row.classList.add('dir-dragging');
try {
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/plain', row.getAttribute('data-id') || '');
} catch (err) { /* IE */ }
}
function onDragOver(e) {
if (!dragRow) return;
var target = e.target.closest('tr.dir-item-row');
if (!target || target === dragRow) return;
if ((target.getAttribute('data-parent-id') || '') !== (dragRow.getAttribute('data-parent-id') || '')) {
return;
}
e.preventDefault();
var tbody = target.parentNode;
var rect = target.getBoundingClientRect();
var before = (e.clientY - rect.top) < rect.height / 2;
if (before) {
tbody.insertBefore(dragRow, target);
} else {
tbody.insertBefore(dragRow, target.nextSibling);
}
}
function onDrop(e) {
e.preventDefault();
}
function onDragEnd() {
if (!dragRow) return;
var row = dragRow;
dragRow.classList.remove('dir-dragging');
dragRow = null;
saveOrder(row);
}
function bind() {
var tbody = document.getElementById('dir-items-tbody');
if (!tbody || tbody.getAttribute('data-dnd-bound') === '1') return;
if (tbody.getAttribute('data-can-edit') !== '1') return;
tbody.setAttribute('data-dnd-bound', '1');
tbody.addEventListener('dragstart', onDragStart);
tbody.addEventListener('dragover', onDragOver);
tbody.addEventListener('drop', onDrop);
tbody.addEventListener('dragend', onDragEnd);
}
document.addEventListener('DOMContentLoaded', bind);
document.addEventListener('htmx:afterSwap', bind);
document.addEventListener('htmx:afterSettle', bind);
})();