InteractJs перетаскивать: карты не падают в правильном положенииJavascript

Форум по Javascript
Ответить
Anonymous
 InteractJs перетаскивать: карты не падают в правильном положении

Сообщение Anonymous »

Я использую функции Draggebable и Dropzone от InteractJS для реализации пользовательского интерфейса перетаскивания, но мои карты не приземляются в правильном положении в зонах Drop. Конечная позиция смещена, иногда дефолт на 0 или неправильно разрешает (например, 5 вместо 2). Я подтвердил, что Contentzones содержит правильные области падения, но Dropzone не всегда соответствует их должным образом. Как я могу гарантировать, что сброшенные элементы правильно выровняются с их ожидаемыми позициями? В частности, я получаю журнал консоли: индекс недопустимого падения: 5. Область Dropzone в этом случае имеет только 3 (я ограничиваю рабочую область 3 Dropzones в группе элементов), хотя на странице есть больше капель. Я попытался ограничить его только в этой области, но что -то все еще не так, и это сообщает о позиции 5 в качестве моей целевой области Dropzone. Я не понимаю. Было бы вечно благодарно за помощь.interact('.content').dropzone({
accept: '.card',
overlap: 0.5,
ondrop: function(event){
const dragged = event.relatedTarget;
const dropzone = event.target;

const contentZones = Array.from(document.querySelectorAll('.content'));
const startPosition = dragged.originalContentIndex ?? contentZones.indexOf(dragged.closest('.draggable-content'));
const endPosition = contentZones.indexOf(dropzone);

// Validate positions
if (endPosition === -1 || startPosition === endPosition) {
console.log('Invalid move detected:', { startPosition, endPosition });
return;
}

// Handle existing card first
const existing = dropzone.querySelector('.card');
if (existing && existing !== dragged) {
// Remove existing card before any other DOM changes
dropzone.removeChild(existing);

// Calculate next position
let nextIndex = endPosition + 1;
if (nextIndex >= contentZones.length) {
nextIndex = 0;
}

//const targetZone = contentZones[nextIndex];
const targetZone = contentZones[endPosition];
if (!targetZone) {
console.error(` drop zone not found at index ${endPosition}`);
return;
}

console.log(`Target drop zone confirmed:`, targetZone.id || 'No ID');

// Move existing card
/*targetZone.appendChild(existing);
resetElementStyle(existing);*/

// Update backend for existing card
const existingGroupID = existing.querySelector('.dropdown-item[data-group-id]')?.getAttribute('data-group-id');
const existingItemID = existing.querySelector('.dropdown-item[data-group-id]')?.getAttribute('data-item-id');
const existingAppTreeID = existing.querySelector('.dropdown-item[data-applicationtreeid]')?.getAttribute('data-applicationtreeid');

if (existingGroupID && existingItemID && existingAppTreeID) {
/*moveItemMultipleLevels(
existingAppTreeID,
existingGroupID,
existingItemID,
'down',
1,
endPosition,
nextIndex,
dropzone
);*/
}
}

// Handle dragged card
if (dragged.parentNode) {
//dragged.parentNode.removeChild(dragged);
}

/*dropzone.appendChild(dragged);
resetElementStyle(dragged);*/

// Update backend for dragged card
const direction = endPosition > startPosition ? 'down' : 'up';
const levels = Math.abs(endPosition - startPosition);

const dropdownItem = dragged.querySelector('.dropdown-item[data-group-id]');
if (dropdownItem) {
const groupID = dropdownItem.getAttribute('data-group-id');
const itemID = dropdownItem.getAttribute('data-item-id');
const applicationTreeID = dropdownItem.getAttribute('data-applicationtreeid');

console.log('Available move actions:', Array.from(dragged.querySelectorAll('.dropdown-item')).map(action => ({
href: action.getAttribute('href'),
groupID: action.getAttribute('data-group-id'),
itemID: action.getAttribute('data-item-id'),
applicationTreeID: action.getAttribute('data-applicationtreeid')
})));

if (groupID && itemID && applicationTreeID && levels > 0) {
//alert(startPosition);
//alert(endPosition);
moveItemMultipleLevels(
applicationTreeID,
groupID,
itemID,
direction,
levels,
startPosition,
endPosition,
dropzone
);
}
}

// Update tracking
//dragged.originalContentIndex = endPosition;
}
});

interact('.card').draggable({
inertia: false,
autoScroll: true,
listeners: {
start(event) {
//alert('start');
const target = event.target;
const rect = target.getBoundingClientRect();

dragStartPosition.x = event.clientX;
dragStartPosition.y = event.clientY;
console.log('drag start event.clientY: ' + event.clientY);

dragOffset.x = event.clientX - rect.left;
dragOffset.y = event.clientY - rect.top;

const computedStyle = window.getComputedStyle(target);

target.originalStyles = {
width: computedStyle.width,
height: computedStyle.height,
minWidth: computedStyle.minWidth,
minHeight: computedStyle.minHeight,
maxWidth: computedStyle.maxWidth,
maxHeight: computedStyle.maxHeight,
position: computedStyle.position,
flex: computedStyle.flex,
flexBasis: computedStyle.flexBasis,
flexGrow: computedStyle.flexGrow,
flexShrink: computedStyle.flexShrink
};

const deltaX = event.clientX - dragStartPosition.x;
const deltaY = event.clientY - dragStartPosition.y;
direction = Math.abs(deltaX) > Math.abs(deltaY)
? (deltaX > 0 ? 'down' : 'up')
: (deltaY > 0 ? 'down' : 'up');

const contentZones = Array.from(document.querySelectorAll('.content'));
target.originalContentIndex = contentZones.indexOf(target.closest('.content'));
startPosition = contentZones.indexOf(target.closest('.content'));

target.style.width = computedStyle.width;
target.style.height = computedStyle.height;
target.style.minWidth = computedStyle.width;
target.style.minHeight = computedStyle.height;
target.style.maxWidth = computedStyle.width;
target.style.maxHeight = computedStyle.height;
target.style.flex = 'none';
target.style.position = 'fixed';
target.style.zIndex = 1000;
target.style.left = (event.clientX - dragOffset.x) + 'px';
target.style.top = (event.clientY - dragOffset.y) + 'px';
target.classList.add('dragging');
},

move(event) {
const target = event.target;
target.style.left = (event.clientX - dragOffset.x) + 'px';
target.style.top = (event.clientY - dragOffset.y) + 'px';
dragLastPosition.x = event.clientX;
dragLastPosition.y = event.clientY;

// Track zones moved over for cards
const elementsUnder = document.elementsFromPoint(event.clientX, event.clientY);
//console.log('Elements detected at drop point:', elementsUnder.map(el => el.className));
const containerUnder = elementsUnder.find(el => el.classList.contains('content'));
/*if (containerUnder) {
zonesMovedOver.add(containerUnder);
}*/
const correctedLevelsMoved = Math.min(zonesMovedOver.size - 1, 2); // Prevent excessive zone shifts
const endPosition = startPosition + (direction === 'up' ? -1 : 1) * correctedLevelsMoved;

if (containerUnder && !zonesMovedOver.has(containerUnder)) {
//alert('added!');
zonesMovedOver.add(containerUnder);
console.log('Added container:', containerUnder.id);
}

},

end(event) {
const target = event.target;

// Reset styles
target.classList.remove('dragging');
Object.entries(target.originalStyles).forEach(([key, value]) => {
target.style[key] = value;
});
target.style.position = 'relative';
target.style.left = '0';
target.style.top = '0';

const contentZones = Array.from(document.querySelectorAll('.content'));
const startPosition = target.originalContentIndex ?? contentZones.indexOf(target.closest('.content'));
const endPosition = target._dropIndex;

// Only proceed if we have a valid drop
if (endPosition === undefined || startPosition === endPosition) return;

const direction = endPosition > startPosition ? 'down' : 'up';
const levels = Math.abs(endPosition - startPosition);
alert('this moveItemMultipleLevels, direction: ' + direction);

const dropzone = contentZones[endPosition];
const existing = dropzone.querySelector('.card');

// Move existing card first if needed
if (existing && existing !== target) {
let nextIndex = endPosition + 1;
if (nextIndex >= contentZones.length) nextIndex = 0;

const targetZone = contentZones[1];
//const targetZone = layoutGroup3.querySelector(`.content:nth-child(${expectedIndex + 1})`);

if (!existing.contains(targetZone)) {
targetZone.appendChild(existing);
resetElementStyle(existing);

const existingGroupID = existing.querySelector('.dropdown-item[data-group-id]')?.getAttribute('data-group-id');
const existingItemID = existing.querySelector('.dropdown-item[data-group-id]')?.getAttribute('data-item-id');
const existingAppTreeID = existing.querySelector('.dropdown-item[data-applicationtreeid]')?.getAttribute('data-applicationtreeid');

if (existingGroupID && existingItemID && existingAppTreeID) {
moveItemMultipleLevels(
existingAppTreeID,
existingGroupID,
existingItemID,
'down',
1,
endPosition,
nextIndex
);
}
} else {
console.warn('Blocked circular move: existing card contains targetZone.');
return;
}
}

// Now drop the dragged card
dropzone.appendChild(target);
resetElementStyle(target);

// Backend update for dragged card
const draggedContainerMenu = target.closest('.card');
if (draggedContainerMenu) {
const dropdownItem = draggedContainerMenu.querySelector('.dropdown-item[data-group-id]');
if (dropdownItem) {
const groupID = dropdownItem.getAttribute('data-group-id');
const itemID = dropdownItem.getAttribute('data-item-id');
const applicationTreeID = dropdownItem.getAttribute('data-applicationtreeid');

if (groupID && itemID && applicationTreeID && levels > 0) {
moveItemMultipleLevels(
applicationTreeID,
groupID,
itemID,
direction,
levels,
startPosition,
endPosition
);
}
}
}

// Update index for future moves
target.originalContentIndex = endPosition;
delete target._dropIndex; // Clean up
}
}
});
< /code>
Здесь oveytemmultiplelevels: < /p>
const moveItemMultipleLevels = async (applicationTreeID, groupID, itemID, direction, levels, startPosition, endPosition, dropzone) => {
console.log('moveItemMultipleLevels called with:', {
applicationTreeID,
groupID,
itemID,
direction,
levels,
startPosition,
endPosition,
dropzone,
moving: `from position ${startPosition} to position ${endPosition}`
});
const moves = [];
try {
const fetchUrl = `index.cfm?fa=MoveGroupItem&ApplicationTreeID=${applicationTreeID}&GroupID=${groupID}&ItemID=${itemID}&direction=${direction}&levels=${levels}`;
const response = await fetch(fetchUrl);
if(!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
moves.push(data);
await new Promise(resolve => setTimeout(resolve, 100));
// Ensure dragged card is properly detected
const draggedCard = window.draggedCard;
if(!draggedCard) {
console.error(`No dragged card detected—dragging not properly initiated.`);
return;
}
console.log('Dragged card detected:', draggedCard.querySelector('.dropdown-item')?.dataset.itemId);
const layoutGroup3 = document.querySelector('#Content_2BEC2B57-5E08-4F32-9DDC6006A8B13775');
if(!layoutGroup3) {
console.error('Layout Group 3 not found');
return;
}
// Get all content zones inside Layout Group 3
const contentZones = Array.from(layoutGroup3.querySelectorAll('.content'));
console.log('Debugging Layout Group 3 structure before drop:');
console.log('Detected zones:', contentZones.map((zone, i) => `Index ${i}: ${zone.id || 'No ID'}`));
console.log('Detected cards:', contentZones.map((zone, i) => `Index ${i}: ${zone.querySelector('.card')?.id || 'Empty'}`));
console.log('Expected drop at index:', endPosition);
document.querySelectorAll('.card').forEach((card, index) => {
card.setAttribute('id', `card-${index}`);
window.draggedCard = card;
console.log(`Assigned ID to card: card-${index}`);
});
console.log('Detected draggable cards:', [...document.querySelectorAll('.card')].map(card => card.id));
contentZones.forEach(zone => {
zone.addEventListener('drop', (event) => {
event.preventDefault();
console.log(`Attempting drop...`);
console.log(`window.draggedCard at drop:`, window.draggedCard);
if(!window.draggedCard) {
console.error('No dragged card detected.');
return;
}
zone.appendChild(window.draggedCard);
console.log(`Dropped card successfully.`);
});
});
// Ensure the drop is happening within valid content zones
if(endPosition < 0 || endPosition >= contentZones.length) {
console.error(`Invalid drop index: ${endPosition}.`);
return;
}
//const targetZone = contentZones[endPosition];
const expectedIndex = contentZones.findIndex(zone => zone === dropzone);
if(expectedIndex === -1) {
console.error(`Dropzone not found in contentZones.`);
return;
}
endPosition = expectedIndex;
console.log('Calculated drop position:', endPosition);
const targetZone = layoutGroup3.querySelector(`.content:nth-child(${expectedIndex + 1})`);
if(!targetZone) {
console.error(`Target drop zone not found at index ${endPosition}`);
return;
}
console.log(`Target drop zone confirmed:`, targetZone.id || 'No ID');
// Move the dragged card to the new position
console.log('targetZone');
console.log(targetZone);
console.log('draggedCard');
console.log(draggedCard);
console.log('endPosition');
console.log(endPosition);
if(draggedCard.parentNode) {
draggedCard.parentNode.removeChild(draggedCard);
}
targetZone.appendChild(draggedCard);
console.log(`Dragged card moved to position ${endPosition}`);
// Cleanup hover effect
contentZones.forEach(zone => zone.classList.remove('hovered'));
return moves;
} catch (error) {
console.error('Error in moveItemMultipleLevels:', error);
throw error;
}
};
< /code>
Я попытался отлаживать, регистрируя обнаруженные зоны и проверив Dropzone против Contentzones, но Dropzone не всегда обнаруживается в ожидаемом месте, и карты иногда приземляются в непреднамеренных районах. Я ищу руководство по обеспечению точного позиционирования в зонах капель.

Подробнее здесь: https://stackoverflow.com/questions/796 ... t-position
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Javascript»