wake-up-neo.com

jQuery Draggable zeigt den Helfer an der falschen Stelle, nachdem die Seite gescrollt wurde

Ich verwende jQuery ziehbar und ziehbar für ein Arbeitsplanungssystem, das ich entwickle. Benutzer ziehen Aufträge an einen anderen Tag oder Benutzer, und anschließend werden die Daten mithilfe eines Ajax-Aufrufs aktualisiert.

Alles funktioniert einwandfrei, außer wenn ich auf der Hauptseite nach unten scrolle (Jobs werden in einem großen Wochenplaner angezeigt, der über den unteren Rand meines Browserfensters hinausgeht). Wenn ich versuche, ein ziehbares Element hierher zu ziehen, wird das Element über meinem Mauszeiger in der gleichen Anzahl von Pixeln angezeigt, wie ich nach unten gescrollt habe.

Ich verwende jQuery 1.6.0 und jQuery UI 1.8.12.

Ich bin sicher, es gibt eine Offset-Funktion, die ich hinzufügen muss, aber ich weiß nicht, wo ich sie anwenden soll oder ob es einen besseren Weg gibt. Hier ist mein .draggable() Initialisierungscode:

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

Irgendeine Idee, was ich tun kann, um das zu beheben?

78
Alex

Dies könnte ein verwandter Fehlerbericht sein, den es schon eine ganze Weile gibt: http://bugs.jqueryui.com/ticket/374

Es scheint auf jedem Browser zu passieren, den ich getestet habe (Chrome, FF4, IE9). Es gibt verschiedene Möglichkeiten, dieses Problem zu umgehen:

1. Verwenden Sie position:absolute; In Ihrer CSS. Absolut positionierte Elemente scheinen nicht betroffen zu sein.

2. Vergewissern Sie sich, dass für das übergeordnete Element (Ereignis, wenn es sich um den Hauptteil handelt) overflow:auto; Festgelegt ist. Mein Test hat gezeigt, dass diese Lösung die Position korrigiert, aber die automatische Bildlauffunktion deaktiviert. Sie können weiterhin mit dem Mausrad oder den Pfeiltasten scrollen.

3. Wenden Sie das im obigen Fehlerbericht vorgeschlagene Update manuell an und testen Sie gründlich, ob es andere Probleme verursacht.

4. Warten Sie auf eine offizielle Lösung. Es ist für jQuery UI 1.9 geplant, obwohl es in der Vergangenheit einige Male verschoben wurde.

5. Wenn Sie sicher sind, dass dies in jedem Browser der Fall ist, können Sie diese Hacks in die Ereignisse der betroffenen Draggables einfügen, um die Berechnungen zu korrigieren. Es sind jedoch viele verschiedene Browser zu testen, daher sollte es nur als letzter Ausweg verwendet werden:

$('.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;
   }
});
104
DarthJDG

Diese Lösung funktioniert, ohne die Position von irgendetwas anzupassen. Sie klonen einfach das Element und machen es absolut positioniert.

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

Der Helfer kann eine Funktion sein, die das zu ziehende DOM-Element zurückgeben muss.

43
mordy

Das hat bei mir funktioniert:

start: function (event, ui) {
   $(this).data("startingScrollTop",window.pageYOffset);
},
drag: function(event,ui){
   var st = parseInt($(this).data("startingScrollTop"));
   ui.position.top -= st;
},
11
Ashraf Fayad

Entschuldigung, dass Sie eine andere Antwort geschrieben haben. Da keine der Lösungen in der obigen Antwort von mir verwendet werden konnte, habe ich viel gegoogelt und viele frustrierende kleinere Änderungen vorgenommen, bevor ich eine andere vernünftige Lösung gefunden habe.

Dieses Problem tritt anscheinend immer dann auf, wenn für any der übergeordneten Elemente position auf 'relative' gesetzt ist. Ich musste mein Markup neu mischen und mein CSS ändern, aber indem ich diese Eigenschaft von allen Eltern entfernte, war ich in der Lage, .sortable() in allen Browsern richtig zum Laufen zu bringen.

7
Joshua Bambrick

Es sieht so aus, als käme dieser Fehler sehr oft vor und jedes Mal gibt es eine andere Lösung. Nichts von alledem oder irgendetwas anderes, was ich im Internet gefunden habe, hat funktioniert. Ich verwende jQuery 1.9.1 und Jquery UI 1.10.3. So habe ich es behoben:

$(".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();
  }
});

Funktioniert in FF, IE, Chrome, ich habe es noch nicht in anderen Browsern getestet.

7
kazmer

Ich lösche den Überlauf:

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

Und es funktioniert perfekt!

5
Miguel Puig

Dieser Fehler wurde nach http://bugs.jqueryui.com/ticket/6817 verschoben und seit ungefähr 5 Tagen (16. Dezember 2013 oder so) scheint er endlich behoben worden zu sein. Der derzeitige Vorschlag ist, den neuesten Entwicklungsstand von http://code.jquery.com/ui/jquery-ui-git.js zu verwenden oder abzuwarten version 1.10.4, die dieses Update enthalten sollte.

Bearbeiten: Es scheint, dass dieses Update jetzt Teil von http://bugs.jqueryui.com/ticket/9315 ist, von dem wird nicht vor Version 1.11 gelöscht. Die Verwendung der oben verlinkten Quellcodeverwaltungsversion von jQuery scheint das Problem für mich und @Scott Alexander zu beheben (Kommentar unten).

5
Patrick

Scheint bemerkenswert, dass dieser Fehler so lange behoben sein sollte. Für mich ist es ein Problem auf Safari und Chrome (d. H. Den Webkit-Browsern), aber nicht auf IE7/8/9 oder Firefox, die alle gut funktionieren.

Ich fand, dass die Einstellung "Absolut" oder "Fest", mit oder ohne "Wichtig", nicht hilfreich war. Am Ende fügte ich meiner Drag-Handler-Funktion eine Zeile hinzu:

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

Ich hatte erwartet, dass ich diese Linie webkit-spezifisch machen musste, aber seltsamerweise funktionierte sie überall gut. (Erwarten Sie einen Kommentar von mir, der bald sagt: "Äh, nein, tatsächlich hat er alle anderen Browser durcheinander gebracht.")

4
Allen

was ich getan habe ist:

$("#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);
         }
        });
3
Pankaj Sharma

Ich hatte das gleiche Problem und stellte fest, dass dies alles an einer bootstrap= navbar "navbar-fixed-top" -Klasse mit der Position "fixed" lag, die mein <body> 60px niedriger als <html> oben. Als ich also ziehbare Formulare auf meiner Site verschoben habe, erschien der Cursor 60px über dem Formular.

Sie können dies im Chrome Debugging-Tool in der Elements-Oberfläche sehen, indem Sie auf <body> Tag und Sie werden eine Lücke zwischen der Oberseite und dem Körper sehen.

Da ich diese Navigationsleiste in allen meinen Anwendungen verwende und meinen Initialisierungsaufruf nicht so ändern wollte, dass er für jedes Formular (gemäß der Prozedur von DarthJDG) gezogen wird. Ich habe mich entschlossen, das ziehbare Widget auf diese Weise zu erweitern und meiner ziehbaren Initialisierung einfach ein yOffset hinzuzufügen.

(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);

Wenn ich jetzt das ziehbare Element/Formular in einer Site mit bootstrap navbar:

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

Natürlich müssen Sie experimentieren, um den richtigen yOffset für Ihre eigene Site zu ermitteln.

Trotzdem danke ich DarthJDG, der mir die richtige Richtung gezeigt hat. Prost!

1
fled

Ich bin mir nicht sicher, ob dies in jedem Fall funktionieren wird, aber diese Problemumgehung habe ich nur für mich in all den verschiedenen Situationen durchgeführt, die ich testen musste (und in denen die zuvor vorgeschlagenen Lösungen hier und anderswo alle fehlgeschlagen sind).

(function($){
$.ui.draggable.prototype._getRelativeOffset = function()
{
    if(this.cssPosition == "relative") {
        var p = this.element.position();
        return {
            top: p.top - (parseInt(this.helper.css("top"),10) || 0)/* + this.scrollParent.scrollTop()*/,
            left: p.left - (parseInt(this.helper.css("left"),10) || 0)/* + this.scrollParent.scrollLeft()*/
        };
    } else {
        return { top: 0, left: 0 };
    }
};
}(jQuery));

(Ich habe es dem jQuery.ui-Tracker übermittelt, um zu sehen, was sie darüber denken. Wäre cool, wenn der 4-jährige Fehler endlich behoben werden könnte: /)

1
vor

Ich konnte das gleiche Problem beheben, indem ich display: inline-block Zu den gezogenen Elementen hinzufügte

Das Hinzufügen von position: relative Hat bei mir NICHT funktioniert (jQuery überschreibt es beim Drag-Start mit position: absolute)

Verwendete jQuery-Versionen:

  • jQuery - 1.7.2
  • jQuery UI - 1.11.4
1
Plamen

Dies scheint die Problemumgehung zu tun, ohne die Position zu verwenden: absolute in der übergeordneten :)

$("body").draggable({
     drag: function(event, ui) { 
         return false; 
     } 
});
1
TomCe

Das hat bei mir funktioniert, nachdem ich alles, was ich über das Problem gelesen habe, angepasst habe.

$(this).draggable({
  ...
  start: function (event, ui) {
    $(this).data("scrollposTop", $('#elementThatScrolls').scrollTop();
    $(this).data("scrollposLeft", $('#elementThatScrolls').scrollLeft();
  },
  drag: function (event, ui) {
    ui.position.top += $('#elementThatScrolls').scrollTop();
    ui.position.left += $('#elementThatScrolls').scrollLeft();
  },
  ...
}); 

* elementThatScrolls ist das übergeordnete oder übergeordnete Element mit Überlauf: auto;

Berechnet die Position des Bildlaufelements und fügt die Position des Hilfsprogramms bei jedem Verschieben/Ziehen hinzu.

Hoffe das hilft jemandem, da ich viel Zeit damit verschwendet habe.

1
Rnubi

Ich verwende JQuery draggable für Firefox 21.0 und habe das gleiche Problem. Der Cursor bleibt einen Zentimeter über dem Hilfsbild. Ich denke, dies ist ein Problem in der JQuery selbst, das immer noch nicht gelöst wurde. Ich habe eine Problemumgehung für dieses Problem gefunden, bei der die Eigenschaft "cursorAt" der Draggable verwendet wird. Ich habe es wie folgt benutzt, aber man kann es entsprechend seiner Anforderung ändern.

$('.dragme').draggable({
helper: 'clone',    
cursor: 'move',    
cursorAt: {left: 50, top: 80}
});

Hinweis: Dies gilt für alle Browser. Nachdem Sie diesen Code verwendet haben, überprüfen Sie Ihre Seite in allen Browsern, um die richtige linke und obere Position zu ermitteln.

1
impiyush

Ich benutze ein Sticky-Navi an der Spitze und dachte, das war der Grund für das Scroll-Problem, das alle anderen zu haben scheinen. Ich habe die Idee aller anderen mit cursorAt ausprobiert, ich habe Containment ausprobiert und es hat nichts funktioniert, AUSSER, dass ich meinen HTML-Überlauf im CSS deaktiviert habe! Wahnsinn, wie ein bisschen CSS alles vermasselt. Das habe ich gemacht und es funktioniert wie ein Zauber:

html {
  overflow-x: unset;
}

body {
  overflow-x: hidden;
}
0
Altus Nix

Ich habe hier verschiedene Antworten ausprobiert, einschließlich der Aktualisierung von jQuery, und festgestellt, dass dies für mich funktioniert. Ich habe dies auf den neuesten chrome und IE getestet. Ich denke, dies wird ein Problem mit unterschiedlichen Lösungen sein, abhängig von Ihrem UI-Layout.

$('{selector}').draggable({
    start: function(event, ui) {
        ui.position.top -= $(document).scrollTop();
    },
    drag: function(event, ui) {
        ui.position.top -= $(document).scrollTop();
    }
});
0
Lee Willis

Ich habe jQueryUi draggable beendet und bin umgezogen, um ein besseres Plugin namens jquery.even.drag zu verwenden, viel kleinerer Code, ohne den ganzen Mist, den jQueryUI hat.

Ich habe eine Demoseite mit diesem Plugin in einem Container erstellt, der folgende Position hat: behoben

Demo

Hoffe das hilft jemandem, denn dieses Problem ist GROSS.

0
vsync

Verwenden appendTo: "body' und setze die Position mit cursorAt. Das funktioniert gut für mich.

Example of my icon following the mouse cursor even after scrolling the page

$('.js-tire').draggable
      tolerance: 'fit',
      appendTo: 'body',
      cursor: 'move',
      cursorAt:
        top: 15,
        left: 18
      helper: (event) ->
        $('<div class="tire-icon"></div>').append($('<img src="/images/tyre_32_32.png" />'))
      start: (event, ui) ->
        if $(event.target).hasClass 'in-use'
          $('.js-send-to-maintenance-box').addClass 'is-highlighted'
        else
          $('.ui-droppable').addClass 'is-highlighted'
      stop: (event, ui) ->
        $('.ui-droppable')
          .removeClass 'is-highlighted'
          .removeClass 'is-dragover'
0
Michelle Diniz

Warum nicht die Cursorposition einnehmen? Ich benutze das sortierbare Plugin und behebe es mit diesem Code:

sort: function(e, ui) {
    $(".ui-sortable-handle.ui-sortable-helper").css({'top':e.pageY});
}
0
Aztrozero

Ich hatte ein ähnliches Problem, nur mit bestimmten IE 10 unter Windows 8. Alle anderen Browser funktionierten einwandfrei. Das Entfernen von cursorAt: {top: 0} löste das Problem.

0
nmm