Add drag-and-drop functionality for service reordering with localStorage support
This commit is contained in:
168
js/drag-drop.js
Normal file
168
js/drag-drop.js
Normal file
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* drag-drop.js - Drag and drop service reordering
|
||||
*/
|
||||
|
||||
const STORAGE_KEY_ORDER = 'services-order';
|
||||
|
||||
// Load saved order from localStorage
|
||||
function loadSavedOrder() {
|
||||
try {
|
||||
const saved = localStorage.getItem(STORAGE_KEY_ORDER);
|
||||
return saved ? JSON.parse(saved) : {};
|
||||
} catch (e) {
|
||||
console.error('Error loading saved order:', e);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// Save order to localStorage
|
||||
function saveSavedOrder(orderMap) {
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY_ORDER, JSON.stringify(orderMap));
|
||||
} catch (e) {
|
||||
console.error('Error saving order:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply saved order to service groups
|
||||
function applySavedOrder() {
|
||||
const orderMap = loadSavedOrder();
|
||||
|
||||
document.querySelectorAll('.service-group').forEach(group => {
|
||||
const groupName = group.querySelector('h2')?.textContent;
|
||||
if (!groupName || !orderMap[groupName]) return;
|
||||
|
||||
const container = group.querySelector('.services-grid');
|
||||
if (!container) return;
|
||||
|
||||
const cards = Array.from(container.querySelectorAll('.service-card'));
|
||||
const orderedIds = orderMap[groupName];
|
||||
|
||||
// Sort cards based on saved order
|
||||
cards.sort((a, b) => {
|
||||
const aId = a.dataset.serviceId;
|
||||
const bId = b.dataset.serviceId;
|
||||
const aIndex = orderedIds.indexOf(aId);
|
||||
const bIndex = orderedIds.indexOf(bId);
|
||||
|
||||
if (aIndex === -1 && bIndex === -1) return 0;
|
||||
if (aIndex === -1) return 1;
|
||||
if (bIndex === -1) return -1;
|
||||
return aIndex - bIndex;
|
||||
});
|
||||
|
||||
// Re-append in sorted order
|
||||
cards.forEach(card => container.appendChild(card));
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize drag and drop
|
||||
function initDragDrop() {
|
||||
let draggedElement = null;
|
||||
let draggedGroup = null;
|
||||
|
||||
document.addEventListener('dragstart', (e) => {
|
||||
if (e.target.classList.contains('service-card')) {
|
||||
draggedElement = e.target;
|
||||
draggedGroup = e.target.closest('.service-group');
|
||||
e.target.style.opacity = '0.5';
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
e.dataTransfer.setData('text/html', e.target.innerHTML);
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('dragend', (e) => {
|
||||
if (e.target.classList.contains('service-card')) {
|
||||
e.target.style.opacity = '1';
|
||||
|
||||
// Remove all drop indicators
|
||||
document.querySelectorAll('.service-card').forEach(card => {
|
||||
card.classList.remove('drag-over');
|
||||
});
|
||||
|
||||
// Save the new order
|
||||
saveCurrentOrder();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('dragover', (e) => {
|
||||
if (e.preventDefault) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
const target = e.target.closest('.service-card');
|
||||
if (target && target !== draggedElement && draggedElement) {
|
||||
const targetGroup = target.closest('.service-group');
|
||||
|
||||
// Only allow reordering within the same group
|
||||
if (targetGroup === draggedGroup) {
|
||||
e.dataTransfer.dropEffect = 'move';
|
||||
|
||||
// Remove previous indicators
|
||||
document.querySelectorAll('.service-card').forEach(card => {
|
||||
card.classList.remove('drag-over');
|
||||
});
|
||||
|
||||
// Add indicator
|
||||
target.classList.add('drag-over');
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
document.addEventListener('drop', (e) => {
|
||||
if (e.stopPropagation) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
const target = e.target.closest('.service-card');
|
||||
if (target && target !== draggedElement && draggedElement) {
|
||||
const targetGroup = target.closest('.service-group');
|
||||
|
||||
// Only allow dropping within the same group
|
||||
if (targetGroup === draggedGroup) {
|
||||
const container = target.parentNode;
|
||||
const targetIndex = Array.from(container.children).indexOf(target);
|
||||
const draggedIndex = Array.from(container.children).indexOf(draggedElement);
|
||||
|
||||
if (draggedIndex < targetIndex) {
|
||||
container.insertBefore(draggedElement, target.nextSibling);
|
||||
} else {
|
||||
container.insertBefore(draggedElement, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
target?.classList.remove('drag-over');
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Make service cards draggable
|
||||
document.querySelectorAll('.service-card').forEach(card => {
|
||||
card.setAttribute('draggable', 'true');
|
||||
});
|
||||
}
|
||||
|
||||
// Save current order of all groups
|
||||
function saveCurrentOrder() {
|
||||
const orderMap = {};
|
||||
|
||||
document.querySelectorAll('.service-group').forEach(group => {
|
||||
const groupName = group.querySelector('h2')?.textContent;
|
||||
if (!groupName) return;
|
||||
|
||||
const cards = group.querySelectorAll('.service-card');
|
||||
const order = Array.from(cards).map(card => card.dataset.serviceId);
|
||||
orderMap[groupName] = order;
|
||||
});
|
||||
|
||||
saveSavedOrder(orderMap);
|
||||
}
|
||||
|
||||
// Export for use in other modules
|
||||
window.dragDropModule = {
|
||||
init: initDragDrop,
|
||||
applySavedOrder: applySavedOrder
|
||||
};
|
||||
Reference in New Issue
Block a user