Можно ли выполнить сортировку при срабатывании события touchstart?

Какова суть задачи и можно ли инициировать сортировку списка, пока мы удерживаем палец на экране и происходит событие touchstart? Например, в библиотеке sortable.js сортировка не начинается, если палец зажат и удерживается. Понятно, что поток блокируется событием, но каким образом можно выйти за пределы этого потока и начать сортировку?
  • 18 сентября 2024 г. 11:53
Ответы на вопрос 2
Технически, вы можете инициировать сортировку при срабатывании события `touchstart`, но это потребует чем-то нестандартного подхода, поскольку многие библиотеки, такие как sortable.js, обрабатывают события так, чтобы избежать путаницы между простым касанием (например, нажатием) и жестом перетаскивания.

### Суть задачи

Суть задачи заключается в том, чтобы начать процесс сортировки элементов списка в момент, когда пользователь касается экрана, без необходимости дожидаться события `touchmove`. Вы хотите, чтобы сортировка начиналась мгновенно по первому прикосновению, несмотря на то, что это может привести к путанице с другими действиями.

### Решение

Для этого можно использовать клиентский JavaScript, избегая библиотек, которые так жестко контролируют поведение событий. Вот общая схема, как это можно реализовать:

1. **Отмените стандартное поведение**: Используйте `touchstart` для запуска сортировки, и сразу же предотвратите дальнейшую обработку событий для того элемента, на который был сделан клик (чтобы избежать конфликта с другими событиями).

2. **Используйте дополнительные события**: После `touchstart`, добавьте обработчик для событий `touchmove` и `touchend`, чтобы контролировать, как элементы перетаскиваются или сортируются.

### Пример реализации

Вот простой пример, как можно это реализовать:

```javascript
const list = document.querySelector('.sortable-list');

list.addEventListener('touchstart', function(event) {
    const targetItem = event.target.closest('.sortable-item');
    if (!targetItem) return;

    // Запускаем сортировку (например, добавляем класс для перемещения)
    targetItem.classList.add('dragging');

    // Отменяем дальнейшую обработку событий
    event.preventDefault();

    // Перемещение элементов
    const onTouchMove = (moveEvent) => {
        // Логика для перемещения элемента
        const touchY = moveEvent.touches[0].clientY;

        // Используйте touchY для определения, куда перемещать элемент
        // Например, перемещаем элемент на новое место в списке
    };

    const onTouchEnd = () => {
        // Завершение сортировки
        targetItem.classList.remove('dragging');
        list.removeEventListener('touchmove', onTouchMove);
        list.removeEventListener('touchend', onTouchEnd);
    };

    list.addEventListener('touchmove', onTouchMove);
    list.addEventListener('touchend', onTouchEnd);
});
```

### Важные замечания

- **Управление событиями**: Убедитесь, что вы правильно добавляете и удаляете обработчики событий, чтобы избежать утечек памяти или конфликтов.
  
- **UX**: Будьте внимательны к пользовательскому опыту: если сортировка будет начинаться слишком рано, это может запутать пользователей. Рассмотрите возможность реализации "гладкого" начала сортировки, которое инициируется, например, при продолжительном нажатии.

- **Свойства браузера**: Некоторые браузеры могут вести себя по-разному при взаимодействии с событиями касания, поэтому обязательно тестируйте вашу реализацию на различных устройствах.

Таким образом, такое поведение возможно и может быть реализовано с использованием JavaScript, избегая встроенной логики из библиотек, которые жестко контролируют поведение сортировки.
Вместо того чтобы полностью полагаться на touchstart, используйте его для начала подготовки, но инициализируйте сортировку с помощью других событий, например touchmove. При этом стоит ограничить область touchmove, чтобы сортировка не начиналась до явного движения пальцем. Также нужно вручную инициировать сортировку. 

var sortable = new Sortable(listElement, {
    animation: 150,
    onStart: function (evt) {
        console.log('Начало сортировки');
    }
});

listElement.addEventListener('touchstart', function (e) {
    var touch = e.touches[0];
    var targetElement = document.elementFromPoint(touch.clientX, touch.clientY);

    sortable._onDragStart({
        target: targetElement,
        clientX: touch.clientX,
        clientY: touch.clientY,
        type: 'touchstart'
    });
}, false);
Похожие вопросы