jQuery Draggable показывает помощник в неправильном месте после прокрутки страницы - PullRequest
78 голосов
/ 26 апреля 2011

Я использую jQuery draggable и droppable для разрабатываемой системы планирования работы.Пользователи перетаскивают задания на другой день или пользователя, а затем данные обновляются с помощью вызова ajax.

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

Я использую jQuery 1.6.0 и jQuery UI 1.8.12.

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

$('.job').draggable({
  zIndex: 20,
  revert: 'invalid',
  helper: 'original',
  distance: 30,
  refreshPositions: true,
});

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

Ответы [ 21 ]

103 голосов
/ 27 апреля 2011

Это может быть связанный отчет об ошибке, который уже давно существует: http://bugs.jqueryui.com/ticket/3740

Похоже, это происходит в каждом браузере, который я тестировал (Chrome, FF4, IE9).Есть несколько способов обойти эту проблему:

1. Используйте position:absolute; в вашем css.Абсолютно позиционированные элементы, похоже, не затрагиваются.

2. Убедитесь, что у родительского элемента (события, если это тело) установлено overflow:auto;.Мой тест показал, что это решение исправляет положение, но отключает функцию автопрокрутки.Вы все еще можете выполнять прокрутку с помощью колесика мыши или клавиш со стрелками.

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

4. Ждите официального исправления.Он запланирован на jQuery UI 1.9, хотя в прошлом он несколько раз откладывался.

5. Если вы уверены, что это происходит в каждом браузере, вы можете поставить эти хакив события затронутых draggables, чтобы исправить вычисления.Тем не менее, нужно протестировать множество различных браузеров, поэтому его следует использовать только в крайнем случае:

$('.drag').draggable({
   scroll:true,
   start: function(){
      $(this).data("startingScrollTop",$(this).parent().scrollTop());
   },
   drag: function(event,ui){
      var st = parseInt($(this).data("startingScrollTop"));
      ui.position.top -= $(this).parent().scrollTop() - st;
   }
});
43 голосов
/ 28 сентября 2012

Это решение работает без настройки положения чего-либо, вы просто клонируете элемент и делаете его абсолютно позиционированным.

$(".sidebar_container").sortable({
  ..
  helper: function(event, ui){
    var $clone =  $(ui).clone();
    $clone .css('position','absolute');
    return $clone.get(0);
  },
  ...
});

Помощник может быть функцией, которая должна возвращать элемент DOM для перетаскивания.

11 голосов
/ 24 января 2014

Это сработало для меня:

start: function (event, ui) {
   $(this).data("startingScrollTop",window.pageYOffset);
},
drag: function(event,ui){
   var st = parseInt($(this).data("startingScrollTop"));
   ui.position.top -= st;
},
7 голосов
/ 13 июля 2012

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

Эта проблема возникает, когда любой родительских элементов имеет position, установленный на «относительный». Мне пришлось переставить мою разметку и изменить свой CSS, но, удалив это свойство у всех родителей, я смог заставить .sortable() работать должным образом во всех браузерах.

7 голосов
/ 04 июня 2013

Похоже, что эта ошибка возникает очень часто, и каждый раз, когда есть другое решение. Ничто из вышеперечисленного или что-либо еще, что я нашел в Интернете, не сработало Я использую jQuery 1.9.1 и Jquery UI 1.10.3. Вот как я это исправил:

$(".dragme").draggable({
  appendTo: "body",
  helper: "clone",
  scroll: false,
  cursorAt: {left: 5, top: 5},
  start: function(event, ui) {
    if(! $.browser.chrome) ui.position.top -= $(window).scrollTop();
  },
  drag: function(event, ui) {
    if(! $.browser.chrome) ui.position.top -= $(window).scrollTop();
  }
});

Работает в FF, IE, Chrome, я еще не тестировал его в других браузерах.

5 голосов
/ 27 сентября 2012

Я удаляю переполнение:

html {overflow-y: scroll; background: #fff;}

И это прекрасно работает!

5 голосов
/ 22 декабря 2013

Эта ошибка была перемещена в http://bugs.jqueryui.com/ticket/6817 и примерно 5 дней назад (16 декабря 2013 г. или около того), похоже, наконец-то исправлена.В настоящее время предлагается использовать последнюю версию разработки от http://code.jquery.com/ui/jquery-ui-git.js или дождаться версии 1.10.4, которая должна содержать это исправление .

Редактировать: Похоже, это исправление теперь может быть частью http://bugs.jqueryui.com/ticket/9315, которое не планируется выпустить до версии 1.11.Использование вышеупомянутой связанной версии исходного кода jQuery, похоже, решает проблему для меня и @Scott Alexander (комментарий ниже).

4 голосов
/ 15 августа 2012

Замечательно, что эта ошибка должна была так долго оставаться незафиксированной.Для меня это проблема в Safari и Chrome (т.е. браузерах webkit), но не в IE7 / 8/9 и не в Firefox, которые все работают нормально.

Я обнаружил, что настройка абсолютная или фиксированная, с или без!, не помогло, в конце концов, я добавил строку в свою функцию обработчика перетаскивания:

ui.position.top += $( 'body' ).scrollTop();

Я ожидал, что мне нужно будет сделать эту строку специфичной для webkit, но, что любопытно, она везде работала нормально.(Ожидайте от меня скорого комментария: «Нет, на самом деле он испортил все остальные браузеры».)

3 голосов
/ 13 апреля 2014

что я сделал это:

$("#btnPageBreak").draggable(
        {
          appendTo: 'body',
          helper: function(event) {
            return '<div id="pageBreakHelper"><img  id="page-break-img"  src="page_break_cursor_red.png" /></div>';
          },
          start: function(event, ui) {
          },
          stop: function(event, ui) {
          },
          drag: function(event,ui){
            ui.helper.offset(ui.position);
         }
        });
1 голос
/ 22 апреля 2017

У меня была та же проблема, и я обнаружил, что все это из-за загрузочного класса navbar "navbar-fixed-top" с позицией в фиксированном положении, которая опускается вниз на <body> 60px ниже <html> top. Поэтому, когда я перемещал перетаскиваемые формы на своем сайте, курсор появлялся на 60px поверх формы.

Вы можете видеть, что в инструменте отладки Chrome, в интерфейсе элементов, нажмите на тег <body>, и вы увидите зазор между верхом и телом.

Поскольку я использую эту панель навигации во всех своих приложениях и не хочу изменять исходный вызов перетаскивания (согласно процедуре DarthJDG) для каждой формы. Я решил расширить перетаскиваемый виджет таким образом и просто добавить yOffset в мою перетаскиваемую инициализацию.

(function($) {
  $.widget("my-ui.draggable", $.ui.draggable, {
    _mouseDrag: function(event, noPropagation) {

      //Compute the helpers position
      this.position = this._generatePosition(event);
      this.positionAbs = this._convertPositionTo("absolute");

      //Call plugins and callbacks and use the resulting position if something is returned
      if (!noPropagation) {
        var ui = this._uiHash();
        if(this._trigger('drag', event, ui) === false) {
          this._mouseUp({});
          return false;
        }
        this.position = ui.position;
      }
      // Modification here we add yoffset in options and calculation
      var yOffset = ("yOffset" in this.options) ? this.options.yOffset : 0;

      if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
      if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top-yOffset+'px';
      if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);

      return false;
    }
  });
})(jQuery);

Теперь, когда я инициализирую перетаскиваемый элемент / форму на сайте с помощью начальной загрузки navbar:

// Make the edit forms draggable
$("#org_account_pop").draggable({handle:" .drag_handle", yOffset: 60});

Конечно, вам придется поэкспериментировать, чтобы определить правильное значение yOffset в соответствии с вашим собственным сайтом.

В любом случае, спасибо DarthJDG, который указал мне верное направление. Ура!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...