refactor(orders): extract form cleanup to reusable module
Moved empty order items cleanup logic from order_form.html to a dedicated order_form_cleanup.js module for better code organization. Changes: - Created order_form_cleanup.js with initOrderFormCleanup() function (~136 lines) - Automatically removes empty order item forms before submit - Handles both new and saved forms differently - Updates TOTAL_FORMS and reindexes remaining forms - Compatible with Django formsets - Updated order_form.html: - Added order_form_cleanup.js include - Added initialization call for #order-form - Removed inline cleanup code (~111 lines) Benefits: - Cleaner template (111 lines removed) - Reusable across other formset-based forms - Easier to test and maintain - Consistent with other extracted modules 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
138
myproject/orders/static/orders/js/order_form_cleanup.js
Normal file
138
myproject/orders/static/orders/js/order_form_cleanup.js
Normal file
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* Order Form Cleanup Module
|
||||
* Автоматическая очистка пустых позиций заказа перед отправкой формы
|
||||
*/
|
||||
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Инициализирует автоочистку пустых форм при submit
|
||||
* @param {Element|string} formElement - DOM элемент формы или селектор
|
||||
*/
|
||||
function initOrderFormCleanup(formElement) {
|
||||
var form = typeof formElement === 'string'
|
||||
? document.querySelector(formElement)
|
||||
: formElement;
|
||||
|
||||
if (!form) {
|
||||
console.error('[OrderFormCleanup] Form not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Обработчик submit - очищаем пустые строки перед валидацией
|
||||
form.addEventListener('submit', function(e) {
|
||||
console.log('[Form Cleanup] Начало очистки пустых форм товаров');
|
||||
|
||||
// Находим все формы товаров
|
||||
var itemForms = Array.from(document.querySelectorAll('.order-item-form'));
|
||||
console.log('[Form Cleanup] Найдено форм:', itemForms.length);
|
||||
|
||||
// Собираем формы для удаления
|
||||
var formsToRemove = [];
|
||||
|
||||
itemForms.forEach(function(itemForm, formIndex) {
|
||||
// Пропускаем уже удалённые формы
|
||||
if (itemForm.classList.contains('deleted')) {
|
||||
console.log('[Form Cleanup] Форма ' + formIndex + ': уже удалена, пропуск');
|
||||
return;
|
||||
}
|
||||
|
||||
// Находим поля
|
||||
var productField = itemForm.querySelector('[name$="-product"]');
|
||||
var kitField = itemForm.querySelector('[name$="-product_kit"]');
|
||||
var quantityField = itemForm.querySelector('[name$="-quantity"]');
|
||||
var priceField = itemForm.querySelector('[name$="-price"]');
|
||||
var idField = itemForm.querySelector('[name$="-id"]');
|
||||
|
||||
// Проверяем значения (пустота = нет значения или значение пустое)
|
||||
var hasProduct = productField && productField.value && productField.value.trim();
|
||||
var hasKit = kitField && kitField.value && kitField.value.trim();
|
||||
var hasQuantity = quantityField && quantityField.value && quantityField.value.trim();
|
||||
var hasPrice = priceField && priceField.value && priceField.value.trim();
|
||||
|
||||
console.log('[Form Cleanup] Форма ' + formIndex + ':');
|
||||
console.log(' - product: ' + (hasProduct || '(пусто)'));
|
||||
console.log(' - kit: ' + (hasKit || '(пусто)'));
|
||||
console.log(' - quantity: ' + (hasQuantity || '(пусто)'));
|
||||
console.log(' - price: ' + (hasPrice || '(пусто)'));
|
||||
|
||||
// Если ВСЁ пусто — это мусорная строка, удаляем
|
||||
var isCompletelyEmpty = !hasProduct && !hasKit && !hasQuantity && !hasPrice;
|
||||
|
||||
console.log(' - Полностью пустая? ' + isCompletelyEmpty);
|
||||
|
||||
if (isCompletelyEmpty) {
|
||||
// Если есть ID (сохранённая позиция) — помечаем на удаление
|
||||
if (idField && idField.value) {
|
||||
console.log(' - Действие: помечаем DELETE (есть ID: ' + idField.value + ')');
|
||||
var deleteCheckbox = itemForm.querySelector('input[name$="-DELETE"]');
|
||||
if (deleteCheckbox) {
|
||||
deleteCheckbox.checked = true;
|
||||
}
|
||||
itemForm.classList.add('deleted');
|
||||
itemForm.style.display = 'none';
|
||||
} else {
|
||||
console.log(' - Действие: помечаем для удаления из formset (нет ID)');
|
||||
// Новая несохранённая форма — помечаем для удаления
|
||||
formsToRemove.push(itemForm);
|
||||
}
|
||||
} else {
|
||||
console.log(' - Действие: оставляем (не пустая, пойдёт на валидацию)');
|
||||
}
|
||||
});
|
||||
|
||||
// Удаляем помеченные формы и пересчитываем индексы
|
||||
if (formsToRemove.length > 0) {
|
||||
console.log('[Form Cleanup] Удаление ' + formsToRemove.length + ' пустых форм...');
|
||||
|
||||
// Удаляем формы из DOM
|
||||
formsToRemove.forEach(function(itemForm) {
|
||||
itemForm.remove();
|
||||
});
|
||||
|
||||
// Обновляем TOTAL_FORMS
|
||||
var totalFormsInput = document.querySelector('[name="items-TOTAL_FORMS"]');
|
||||
if (totalFormsInput) {
|
||||
var oldTotal = parseInt(totalFormsInput.value);
|
||||
var newTotal = oldTotal - formsToRemove.length;
|
||||
console.log('[Form Cleanup] Обновление TOTAL_FORMS: ' + oldTotal + ' → ' + newTotal);
|
||||
totalFormsInput.value = newTotal;
|
||||
}
|
||||
|
||||
// Пересчитываем индексы оставшихся форм
|
||||
var remainingForms = Array.from(document.querySelectorAll('.order-item-form:not(.deleted)'));
|
||||
console.log('[Form Cleanup] Пересчёт индексов для ' + remainingForms.length + ' оставшихся форм...');
|
||||
|
||||
remainingForms.forEach(function(itemForm, newIndex) {
|
||||
// Находим все поля с name="items-N-..."
|
||||
var fields = itemForm.querySelectorAll('[name^="items-"]');
|
||||
fields.forEach(function(field) {
|
||||
var name = field.getAttribute('name');
|
||||
// Меняем индекс: items-СТАРЫЙ-поле → items-НОВЫЙ-поле
|
||||
var newName = name.replace(/^items-\d+/, 'items-' + newIndex);
|
||||
if (name !== newName) {
|
||||
console.log('[Form Cleanup] Переименование: ' + name + ' → ' + newName);
|
||||
field.setAttribute('name', newName);
|
||||
|
||||
// Обновляем ID тоже (для связи с label)
|
||||
if (field.id) {
|
||||
var newId = field.id.replace(/^id_items-\d+/, 'id_items-' + newIndex);
|
||||
field.setAttribute('id', newId);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
console.log('[Form Cleanup] Очистка завершена');
|
||||
// Всё остальное идёт на валидацию Django как есть
|
||||
});
|
||||
|
||||
console.log('[OrderFormCleanup] Initialized for form:', form.id || form);
|
||||
}
|
||||
|
||||
// Экспорт
|
||||
window.initOrderFormCleanup = initOrderFormCleanup;
|
||||
|
||||
})(window);
|
||||
Reference in New Issue
Block a user