Bug fixes
This commit is contained in:
168
components/fallback-swipe-card.js
Normal file
168
components/fallback-swipe-card.js
Normal file
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* Fallback Swipe Card Component
|
||||
* Simple swipe implementation for compatibility mode
|
||||
*/
|
||||
|
||||
export default class FallbackSwipeCard {
|
||||
constructor(options = {}) {
|
||||
this.container = options.container || document.querySelector('.swipe-container');
|
||||
this.onSwipe = options.onSwipe || (() => {});
|
||||
this.threshold = options.threshold || 100;
|
||||
|
||||
this.state = {
|
||||
isDragging: false,
|
||||
startX: 0,
|
||||
startY: 0,
|
||||
moveX: 0,
|
||||
moveY: 0,
|
||||
hasMoved: false,
|
||||
currentImageInfo: null
|
||||
};
|
||||
|
||||
this.card = null;
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.card = this.container.querySelector('.image-card') || this.createCardElement();
|
||||
this.addEventListeners();
|
||||
console.log('FallbackSwipeCard initialized');
|
||||
}
|
||||
|
||||
createCardElement() {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'image-card';
|
||||
card.id = 'current-card';
|
||||
card.setAttribute('role', 'img');
|
||||
card.setAttribute('aria-label', 'Image to be swiped');
|
||||
|
||||
const img = document.createElement('img');
|
||||
img.src = 'data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%22400%22%20height%3D%22400%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20width%3D%22400%22%20height%3D%22400%22%20fill%3D%22%23e0e0e0%22%2F%3E%3Ctext%20x%3D%22200%22%20y%3D%22200%22%20font-size%3D%2220%22%20text-anchor%3D%22middle%22%20alignment-baseline%3D%22middle%22%20fill%3D%22%23999%22%3ELoading...%3C%2Ftext%3E%3C%2Fsvg%3E';
|
||||
img.alt = 'Image';
|
||||
|
||||
const loadingIndicator = document.createElement('div');
|
||||
loadingIndicator.className = 'loading-indicator';
|
||||
loadingIndicator.textContent = 'Loading...';
|
||||
|
||||
card.appendChild(img);
|
||||
card.appendChild(loadingIndicator);
|
||||
this.container.appendChild(card);
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
addEventListeners() {
|
||||
// Mouse events
|
||||
this.card.addEventListener('mousedown', (e) => this.handlePointerDown(e.clientX, e.clientY));
|
||||
document.addEventListener('mousemove', (e) => this.handlePointerMove(e.clientX, e.clientY));
|
||||
document.addEventListener('mouseup', () => this.handlePointerUp());
|
||||
|
||||
// Touch events
|
||||
this.card.addEventListener('touchstart', (e) => {
|
||||
const touch = e.touches[0];
|
||||
this.handlePointerDown(touch.clientX, touch.clientY);
|
||||
}, { passive: true });
|
||||
|
||||
this.card.addEventListener('touchmove', (e) => {
|
||||
const touch = e.touches[0];
|
||||
this.handlePointerMove(touch.clientX, touch.clientY);
|
||||
}, { passive: true });
|
||||
|
||||
this.card.addEventListener('touchend', () => this.handlePointerUp());
|
||||
}
|
||||
|
||||
handlePointerDown(x, y) {
|
||||
this.state.isDragging = true;
|
||||
this.state.startX = x;
|
||||
this.state.startY = y;
|
||||
this.state.hasMoved = false;
|
||||
this.card.classList.add('swiping');
|
||||
}
|
||||
|
||||
handlePointerMove(x, y) {
|
||||
if (!this.state.isDragging) return;
|
||||
|
||||
this.state.moveX = x - this.state.startX;
|
||||
this.state.moveY = y - this.state.startY;
|
||||
|
||||
if (Math.abs(this.state.moveX) > 10 || Math.abs(this.state.moveY) > 10) {
|
||||
this.state.hasMoved = true;
|
||||
}
|
||||
|
||||
// Simple transform without physics
|
||||
this.card.style.transform = `translate(${this.state.moveX}px, ${this.state.moveY}px) rotate(${this.state.moveX * 0.05}deg)`;
|
||||
}
|
||||
|
||||
handlePointerUp() {
|
||||
if (!this.state.isDragging) return;
|
||||
|
||||
this.state.isDragging = false;
|
||||
this.card.classList.remove('swiping');
|
||||
|
||||
const absX = Math.abs(this.state.moveX);
|
||||
const absY = Math.abs(this.state.moveY);
|
||||
|
||||
if (this.state.hasMoved && (absX > this.threshold || absY > this.threshold)) {
|
||||
let direction;
|
||||
if (absX > absY) {
|
||||
direction = this.state.moveX > 0 ? 'right' : 'left';
|
||||
} else {
|
||||
direction = this.state.moveY > 0 ? 'down' : 'up';
|
||||
}
|
||||
|
||||
this.performSwipe(direction);
|
||||
} else {
|
||||
// Reset position
|
||||
this.card.style.transition = 'transform 0.3s ease';
|
||||
this.card.style.transform = '';
|
||||
setTimeout(() => {
|
||||
this.card.style.transition = '';
|
||||
}, 300);
|
||||
}
|
||||
|
||||
this.state.moveX = 0;
|
||||
this.state.moveY = 0;
|
||||
}
|
||||
|
||||
performSwipe(direction) {
|
||||
this.card.classList.add(`swipe-${direction}`);
|
||||
this.onSwipe(direction);
|
||||
|
||||
setTimeout(() => {
|
||||
this.card.classList.remove(`swipe-${direction}`);
|
||||
this.card.style.transform = '';
|
||||
}, 500);
|
||||
}
|
||||
|
||||
setImage(imageInfo) {
|
||||
this.state.currentImageInfo = imageInfo;
|
||||
|
||||
if (!imageInfo) {
|
||||
this.card.innerHTML = '<div class="no-images-message">No more images available.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
const cardImage = this.card.querySelector('img');
|
||||
if (cardImage) {
|
||||
cardImage.src = imageInfo.path;
|
||||
}
|
||||
}
|
||||
|
||||
showLoading() {
|
||||
this.card.classList.add('loading');
|
||||
}
|
||||
|
||||
hideLoading() {
|
||||
this.card.classList.remove('loading');
|
||||
}
|
||||
|
||||
destroy() {
|
||||
// Remove event listeners
|
||||
this.card.removeEventListener('mousedown', this.handlePointerDown);
|
||||
document.removeEventListener('mousemove', this.handlePointerMove);
|
||||
document.removeEventListener('mouseup', this.handlePointerUp);
|
||||
|
||||
// Clean up
|
||||
this.card = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user