JQuery Сортировка и автоматическая прокрутка

Я пытаюсь заставить JQuery Sortable работать, но я столкнулся с небольшой проблемой юзабилити.

Список, который я пытаюсь сортировать, довольно большой (около 200 элементов). Если пользователь пытается перетащить верхний элемент вправо, как только элемент достигнет нижней части видимой части экрана, страница прокручивает небольшое количество, а затем останавливается. Чтобы вызвать более прокрутку вниз, вы должны перемещать мышь круговыми движениями до тех пор, пока элемент не достигнет дна.

Есть ли способ отслеживания положения мыши, когда он перетаскивает элемент и автоматически прокручивает экран вниз?

Ответ 2

В то время как значение функции scrollSensitivity контролирует поведение прокрутки, когда вспомогательный элемент приближается к краю (сверху или снизу) вы можете использовать событие сортировки для безоговорочной прокрутки во время перетаскивания, если вы используете следующий код:

$(".sortable").sortable({
    scroll: true,
    scrollSensitivity: 80,
    scrollSpeed: 3,
    sort: function(event, ui) {
        var currentScrollTop = $(window).scrollTop(),
            topHelper = ui.position.top,
            delta = topHelper - currentScrollTop;
        setTimeout(function() {
            $(window).scrollTop(currentScrollTop + delta);
        }, 5);
    }
});

Не уверен, что это полностью устраняет проблему, которую вы видите, но я обнаружил, что удобство использования с большим списком улучшается с помощью этого подхода. Вот ссылка на jsfiddle.

Ответ 3

Я думаю, что вы можете рассмотреть возможность обработки прокрутки по внешней для сортировки. Я предлагаю использовать таймер и "выход" для сортировки.

Вот фрагмент кода, основанный на демонстрационной странице jQueryUI, вы можете использовать его в качестве начальной точки, если хотите пойти следующим образом:

$(function() {
   var scroll = '';
   var $scrollable = $("#sortable");
   function scrolling(){
     if (scroll == 'up') {
       $scrollable.scrollTop($scrollable.scrollTop()-20);
       setTimeout(scrolling,50);
     }
     else if (scroll == 'down'){
       $scrollable.scrollTop($scrollable.scrollTop()+20);
       setTimeout(scrolling,50);
     }
   }

   $( "#sortable" ).sortable({
      scroll:false,
      out: function( event, ui ) {
        if (!ui.helper) return;
        if (ui.offset.top>0) {
          scroll='down';
        } else {
          scroll='up';
        }
        scrolling();
      },
      over: function( event, ui ) {
        scroll='';
      },
      deactivate:function( event, ui ) {
        scroll='';
      }
    });
    $( "#sortable").disableSelection(); 
});

Вот также рабочий пример: JSBIN

извините
Я не блокировал пример кода и, кстати, был уничтожен. Теперь он вернулся к работе.

Ответ 4

Я удалил overflow-y: scroll из body, чтобы решить эту проблему.

Ответ 5

У меня была отзывчивая таблица с бутстрапом, это не позволило бы ей работать.

не так:

<div class="table-responsive">
   <table>
      ...
   </table>
</div>

как это да:

 <table>
   ...
 </table>

и используйте следующие параметры:

scroll, scrollSensitivity, scrollSpeed

Ответ 6

Окно прокрутки, когда элемент перетаскивается вверх или вниз.

Я не мог получить никаких других ответов. Использование Chrome и сортируемой сетки, которая должна прокручиваться по вертикали, когда элемент перетаскивается в верхний или нижний край окна.

ПРИМЕЧАНИЕ. Это работает только для прокрутки всего окна. Это не будет работать, если у вас есть прокручиваемый раздел внутри окна и нужно прокрутить его.

Я смог получить работать безупречно:

var currentlyScrolling = false;

var SCROLL_AREA_HEIGHT = 40; // Distance from window top and bottom edge.

$(".sortable").sortable({
    scroll: true,

    sort: function(event, ui) {

      if (currentlyScrolling) {
        return;
      }

      var windowHeight   = $(window).height();
      var mouseYPosition = event.clientY;

      if (mouseYPosition < SCROLL_AREA_HEIGHT) {
        currentlyScrolling = true;

        $('html, body').animate({
          scrollTop: "-=" + windowHeight / 2 + "px" // Scroll up half of window height.
        }, 
        400, // 400ms animation.
        function() {
          currentlyScrolling = false;
        });

      } else if (mouseYPosition > (windowHeight - SCROLL_AREA_HEIGHT)) {

        currentlyScrolling = true;

        $('html, body').animate({
          scrollTop: "+=" + windowHeight / 2 + "px" // Scroll down half of window height.
        }, 
        400, // 400ms animation.
        function() {
          currentlyScrolling = false;
        });

      }
    }
});

Версия coffeescript

currentlyScrolling = false
SCROLL_AREA_HEIGHT = 40

sort: (event, ui) ->

  return if currentlyScrolling

  windowHeight = $( window ).height()

  mouseYPosition = event.clientY

  if mouseYPosition < SCROLL_AREA_HEIGHT # Scroll up.
    currentlyScrolling = true
    $( 'html, body' ).animate( { scrollTop: "-=" + windowHeight / 2 + "px" }, 400, () -> currentlyScrolling = false )

  else if mouseYPosition > ( windowHeight - SCROLL_AREA_HEIGHT ) # Scroll down.
    currentlyScrolling = true
    $( 'html, body' ).animate( { scrollTop: "+=" + windowHeight / 2 + "px" }, 400, () -> currentlyScrolling = false )

Ответ 7

Вы можете инициировать события на основе позиции, возвращенной mouseMove. Вот простой учебник: http://jquery-howto.blogspot.com/2009/07/identifying-locating-mouse-position-in.html

Этот учебник может помочь вам приступить к работе: http://valums.com/vertical-scrolling-menu/ И это проходит через тот же эффект: http://www.queness.com/resources/html/scrollmenu/index.html

Ответ 8

Основываясь на ответе @marty, вот тонко настроенный код, который будет:  1. Скорость управления прокруткой  2. Будет прокручиваться вниз и прокручиваться без глюков.  3. Скорость по умолчанию - 7 пикселей за раз  4. Движения менее 7px будут проигнорированы

var previousLocation, previousDelta;
    $( ".selector" ).sortable({
        sort: function(event, ui) {
            var currentScrollTop = $(window).scrollTop(),
                topHelper = ui.position.top,
                delta = topHelper - currentScrollTop;
            setTimeout(function() {
                if((delta < 7 && delta >=0) || (delta > -7 && delta <=0))
                    return;
                if(delta > 7){
                    delta = 7;
                    if((topHelper - previousDelta) < previousLocation){
                        delta = (delta * -1);
                    }
                }
                if(delta < -7){
                    delta = -7;
                    if((topHelper - previousDelta) > previousLocation){
                        delta = (delta * -1);
                    }
                }

                $(window).scrollTop(currentScrollTop + delta);
                previousLocation = topHelper; previousDelta = delta;
            }, 5);
        }
    });