Как можно исправить скрипт, отвечающий за горизонтальную прокрутку?

Как организовать работу селектов внутри блока с горизонтальным скроллом, чтобы они открывались только по клику, а при перетаскивании селект оставался закрытым? У меня уже есть скрипт, который позволяет перетаскивать блок, но столкнулся с проблемой: из-за использования `return false` в обработчике события `mousedown` селекты не открываются. Если убрать этот код, то при перетаскивании за селект он открывается, что нежелательно. 

Вот демо: <a href="https://codepen.io/maxbeat/pen/LEPXjoo" rel="nofollow">https://codepen.io/maxbeat/pen/LEPXjoo</a> 

Актуальный код: 
<pre><code class="javascript">$('.scroll-container').mousedown(function (e) {
		$(this)
			.data('down', true)
			.data('x', e.clientX)
			.data('scrollLeft', this.scrollLeft)
		return false; // предотвращаем стандартное поведение
	}).mousemove(function (e) {
		if ($(this).data('down') == true) {
			this.scrollLeft = $(this).data('scrollLeft') + $(this).data('x') - e.clientX;
			$(this).addClass('dragging');
		}
	}).mouseup(function (e) {
		$(this)
			.data('down', false)
			.removeClass('dragging');
	});
	// если мышка соскакивает с блока, чтобы не залипала потом на нем
	$(document).mouseup(function (e) {
		$('.scroll-container')
		.data('down', false)
		.removeClass('dragging');
	});</code></pre>
  • 24 января 2025 г. 20:54
Ответы на вопрос 2
Для того чтобы исправить ваш скрипт и сделать так, чтобы селекты открывались только по клику, а не при перетаскивании, можно использовать дополнительную логику для определения того, произошло ли перетаскивание элемента или обычный клик.

Вот модифицированный код, который поможет достичь желаемого поведения:

```javascript
$('.scroll-container').mousedown(function (e) {
    // Запоминаем начальные координаты
    $(this)
        .data('down', true)
        .data('x', e.clientX)
        .data('scrollLeft', this.scrollLeft)
        .data('isDragging', false); // Добавляем флаг перетаскивания
    return false; 
}).mousemove(function (e) {
    if ($(this).data('down') == true) {
        this.scrollLeft = $(this).data('scrollLeft') + $(this).data('x') - e.clientX;
        $(this).addClass('dragging');

        // Если перемещение превышает порог, считаем это перетаскиванием
        const threshold = 5; // Порог перемещения
        if (Math.abs(e.clientX - $(this).data('x')) > threshold) {
            $(this).data('isDragging', true);
        }
    }
}).mouseup(function (e) {
    $(this)
        .data('down', false)
        .removeClass('dragging');

    // Если это было обычное нажатие, обрабатываем клик
    if (!$(this).data('isDragging')) {
        // Обрабатываем клик по селекту, если кликнули по выбранному селекту, открываем его
        $(this).find('select').each(function() {
            const selectOffset = $(this).offset();
            if (e.clientX >= selectOffset.left && e.clientX <= selectOffset.left + $(this).outerWidth() &&
                e.clientY >= selectOffset.top && e.clientY <= selectOffset.top + $(this).outerHeight()) {
                $(this).selectpicker('toggle'); // Используйте ваш метод для открытия селекта
            }
        });
    }
    $(this).data('isDragging', false);
});

// Если мышка соскакивает с блока, чтобы не залипала потом на нем
$(document).mouseup(function (e) {
    $('.scroll-container')
        .data('down', false)
        .removeClass('dragging');
});
```

### Объяснение изменений:

1. **Использование флага `isDragging`:** Добавлен флаг `isDragging`, который отслеживает, произошло ли перетаскивание или нет.
  
2. **Порог перемещения:** Установлен порог в 5 пикселей. Если перемещение мыши превышает этот порог, мы начинаем считать, что происходит перетаскивание.

3. **Обработка щелчка:** При `mouseup` проверяем значение флага `isDragging`. Если это было не перетаскивание, тогда проверяем, кликнули ли по селекту и открываем его.

Теперь при перетаскивании селекты не будут открываться, и они откроются только при обычном клике.
Отлавливать, что клик произошел, по селекту, а дальше уже определять поведение. Самое простое, это обернуть код в условие: 
if(e.target.nodeName != "SELECT") {
		$(this)
			.data('down', true)
			.data('x', e.clientX)
			.data('scrollLeft', this.scrollLeft)
		return false; // предотвращаем стандартное поведение
   }
Похожие вопросы