HTML5 DnD dataTransfer setData oder getData funktioniert nicht in jedem Browser außer Firefox

Lesezeit: 10 Minuten

Benutzer-Avatar
Gup3rSuR4c

Bedenken Sie JSFiddle. Es funktioniert gut in Firefox (14.0.1), schlägt jedoch in Chrome (21.0.1180.75), Safari (?) und Opera (12.01?) unter Windows (7) und OS X (10.8) fehl. Soweit ich das beurteilen kann, liegt das Problem bei beiden setData() oder getData() Methoden auf der dataTransfer Objekt. Hier ist der relevante Code aus JSFiddle.

var dragStartHandler = function (e) {
    e.originalEvent.dataTransfer.effectAllowed = "move";
    e.originalEvent.dataTransfer.setData("text/plain", this.id);
};

var dragEnterHandler = function (e) {
    //  dataTransferValue is a global variable declared higher up.
    //  No, I don't want to hear about why global variables are evil,
    //  that's not my issue.
    dataTransferValue = e.originalEvent.dataTransfer.getData("text/plain");

    console.log(dataTransferValue);
};

Soweit ich das beurteilen kann, sollte dies einwandfrei funktionieren, und wenn Sie beim Ziehen eines Elements auf die Konsole schauen, sehen Sie die ausgeschriebene ID, was bedeutet, dass das Element problemlos gefunden und sein ID-Attribut abgerufen wird. Die Frage ist, werden die Daten einfach nicht eingestellt oder die Daten nicht abgerufen?

Ich würde mich über Vorschläge freuen, denn nach einer Woche Arbeit mit drei Versuchen und mehr als 200 Versionen fange ich an, den Verstand zu verlieren. Ich weiß nur, dass es früher in Version 60 oder so funktionierte und dieser spezifische Code sich überhaupt nicht geändert hat …

Tatsächlich besteht einer der Hauptunterschiede zwischen 6X und 124 darin, dass ich die Ereignisbindung von geändert habe live() zu on(). Ich glaube nicht, dass das das Problem ist, aber ich habe ein paar Fehler von Chrome gesehen, wenn es um DnD geht, während ich daran arbeite. Dies wurde entlarvt. Die Ereignisbindungsmethode hat keine Auswirkung auf das Problem.

AKTUALISIEREN

Ich habe eine neue erstellt JSFiddle das entfernt absolut alles und lässt nur die Ereignisbindung und Handler übrig. Ich habe es mit jQuery 1.7.2 und 1.8 mit beiden getestet on() und live(). Das Problem blieb bestehen, also fiel ich eine Ebene tiefer und entfernte alle Frameworks und verwendete reines JavaScript. Die Angelegenheit still bestanden, also ist es basierend auf meinen Tests nicht mein Code, der fehlschlägt. Stattdessen scheinen Chrome, Safari und Opera beide zu implementieren setData() oder getData() Off-Spec oder einfach aus irgendeinem Grund fehlgeschlagen. Bitte korrigieren Sie mich, falls ich falsch liege.

Wie auch immer, wenn Sie sich das neue JSFiddle ansehen, sollten Sie in der Lage sein, das Problem zu replizieren, schauen Sie einfach auf die Konsole, wenn Sie über ein Element ziehen, das zum Akzeptieren eines Drops bestimmt ist. Ich habe weitergemacht und ein Ticket mit eröffnet Chrom. Am Ende mache ich vielleicht immer noch etwas falsch, aber ich weiß an dieser Stelle einfach nicht, wie ich sonst DnD machen soll. Das neue JSFiddle ist so abgespeckt wie es nur geht…

  • Wie unten angemerkt, ist dies ein Problem mit der WHATWG-Spezifikation. Ich habe hier einen Fehler gemeldet – w3.org/Bugs/Public/show_bug.cgi?id=23486

    – broofa

    12. Oktober 2013 um 11:54 Uhr

  • Ich muss PPK zustimmen (danke für den Link in Ihrer eigenen Antwort) – verwenden Sie einfach nicht “html5 native DnD”. Gehen Sie zu “Retro Vanilla”, verwenden Sie einfach die Maus nach unten / bewegen / nach oben, wie in dieser Frage beschrieben stackoverflow.com/questions/18425089/simple-drag-and-drop-code

    – MathekopfinWolken

    26. Juni 2020 um 3:50 Uhr


  • FireFox scheint dataTransfer-Probleme zu haben, die andere Browser nicht haben. Siehe hier: bugzilla.mozilla.org/show_bug.cgi?id=580928

    – ADJenks

    2. Juli 2020 um 23:57 Uhr

Benutzer-Avatar
Gup3rSuR4c

Ok, nach ein bisschen mehr Graben fand ich heraus, dass das Problem eigentlich nicht bei Chrome, Safari und Opera liegt. Was es verriet, war, dass Firefox es unterstützte und ich konnte einfach nicht sagen, dass die anderen Browser versagten, da ich das normalerweise für den IE akzeptieren würde.

Die eigentliche Ursache des Problems ist die DnD-Spezifikation selbst. Gemäß der Spezifikation für die drag, dragenter, dragleave, dragover und dragend Ereignisse ist der Drag Data Store-Modus Sicherheitsmodus. Was ist Sicherheitsmodus du fragst? Es ist:

Für alle anderen Veranstaltungen. Die Formate und Arten in der Drag-Datenspeicherliste von Elementen, die gezogene Daten darstellen, können aufgezählt werden, aber die Daten selbst sind nicht verfügbar und es können keine neuen Daten hinzugefügt werden.

Das bedeutet übersetzt, “Sie haben keinen Zugriff auf die von Ihnen eingestellten Daten, nicht einmal im Nur-Lesen-Modus! Gehen Sie f@&# selbst.”. Wirklich? Wer ist das Genie, das sich das ausgedacht hat?

Um diese Einschränkung zu umgehen, haben Sie nur wenige Möglichkeiten, und ich werde nur zwei skizzieren, die mir eingefallen sind. Ihre erste besteht darin, eine bösartige globale Variable zu verwenden und den globalen Namensraum zu verunreinigen. Ihre zweite Wahl ist die Verwendung der HTML5-localStorage-API, um genau die gleiche Funktionalität auszuführen, die die DnD-API zu Beginn hätte bereitstellen sollen!

Wenn Sie diesen Weg gehen, den ich habe, implementieren Sie jetzt zwei HTML5-APIs, nicht weil Sie wollen zu, sondern weil du haben zu. Jetzt fange ich an zu schätzen PPK schimpft über die Katastrophe dass die HTML5 DnD API ist.

Die Quintessenz ist, dass die Spezifikation geändert werden muss, um den Zugriff auf die gespeicherten Daten zu ermöglichen, auch wenn sie nur im schreibgeschützten Modus sind. In meinem Fall, mit diesem JSFiddleich benutze eigentlich die dragenter als Möglichkeit, auf die Dropzone vorauszuschauen und zu überprüfen, ob ich einen Drop zulassen sollte oder nicht.

In diesem Fall hat Mozilla offenbar die vollständige Einhaltung der Spezifikation abgelehnt, weshalb mein JSFiddle darin einwandfrei funktionierte. Es ist einfach so, dass dies das einzige Mal ist, dass ich die volle Spezifikation nicht unterstütze.

  • +1, das ist wahnsinnig dumm jsfiddle.net/crl/rguLw8z2/1 kann nicht auf anderen Browsern als FF arbeiten

    – caub

    16. November 2015 um 12:33 Uhr

  • Würden sie die Daten zur Verfügung stellen, würde dies grundsätzlich gegen das JavaScript-Sandbox-Prinzip verstoßen. Ich denke also nicht, dass Sie sie sarkastisch Genies nennen sollten, wenn sie tatsächlich einen Weg gefunden haben, diese Funktion zu aktivieren und gleichzeitig Benutzerdaten zu schützen.

    – Pascha Skender

    21. August 2016 um 12:53 Uhr

  • @LorenShqipognja, obwohl ich die DnD-API in den Jahren seit diesem Beitrag nicht mehr verwendet habe und das ursprüngliche Projekt, das diesen Beitrag hervorgebracht hat, ebenfalls verschwunden ist, stehe ich immer noch zu meinem Sarkasmus, weil die Spezifikation immer noch falsch ist. Sie erhalten Methoden zum Lesen und Schreiben von Daten, aber so viel Sie schreiben, Sie können nicht immer lesen, insbesondere in sehr entscheidenden Momenten, um bei Bedarf unterschiedliche Ergebnisse zu erzwingen. Der gesamte Datenteil der Spezifikation ist sinnlos, wenn Sie sich mit LocalStorage, Datenattributen oder etwas anderem “hacken” müssen, anstatt die API bereitzustellen[ working] Funktionalität. Aber ich schweife ab.

    – Gup3rSuR4c

    23. August 2016 um 20:42 Uhr

  • Ich wurde verrückt, als ich versuchte herauszufinden, warum meine Datenübertragung nicht eingestellt wurde

    – iedoc

    25. Juli 2017 um 16:50 Uhr

  • 2018, immer noch damit zu kämpfen. Gibt es eine neue API, die wir verwenden?

    – Yana Agun Siswanto

    22. Oktober 2018 um 10:29 Uhr

Es gibt einen Grund für das “geschützte” Bit…. Drag/Drop kann sich über völlig verschiedene Fenster erstrecken, und sie wollten nicht, dass jemand in der Lage ist, ein “Listener”-DIV zu implementieren, das den Inhalt von allem belauschen würde, was war darüber gezogen (und diese Inhalte vielleicht per AJAX an einen Spionageserver in Elbonia senden). Nur der DROP-Bereich (der eindeutiger unter der Kontrolle des Benutzers steht) bekommt die volle Schaufel.

Ärgerlich, aber ich kann verstehen, warum es als notwendig erachtet werden könnte.

  • Haben Sie einen Link zu der WHATWG-Diskussion, die diesbezüglich stattfand? Ich würde gerne mehr über ihre Argumentation erfahren.

    – broofa

    12. Oktober 2013 um 11:33 Uhr

  • Bitte geben Sie Ihre Quellen an

    – caub

    16. November 2015 um 12:34 Uhr

  • Aber dragend wird auf das gezogene Element gefeuert, richtig? Sie sollten es nicht gegen sich selbst schützen müssen, oder?

    – Svante

    15. Oktober 2017 um 18:38 Uhr

  • Und sie hätten nicht die bewährte Same-Origin-Politik anwenden können? Auch über verschiedene Fenster hinweg sollten Daten innerhalb derselben Domäne zugänglich sein.

    – Lukas

    9. November 2017 um 0:00 Uhr

  • Es gab keine Quelle. Ich arbeitete an einem Problem mit Drag & Drop und hatte beim Lesen einfach einen Gedanken. Sorry, dass ich das nicht früher erwähnt habe.

    – Jens Fiederer

    7. Februar 2018 um 15:05 Uhr

var dragStartHandler = function (e) {
    e.originalEvent.dataTransfer.effectAllowed = "move";
    e.originalEvent.dataTransfer.setData("text/plain", this.id);
};

Das Problem ist mit dem “Text/Klartext”. Die Standardspezifikation in der MSDN-Dokumentation für setData ist nur “Text” (ohne /plain). Chrome akzeptiert /plain, IE jedoch nicht, in keiner Version, die ich ausprobiert habe.

Ich kämpfte mehrere Wochen mit dem gleichen Problem und versuchte herauszufinden, warum meine “Drop”-Ereignisse im IE nicht richtig ausgelöst wurden, während sie es in CHrome taten. Das lag daran, dass die dataTransfer-Daten nicht richtig geladen wurden.

  • Ich konnte nicht von HTML in einem WebBrowser-Objekt innerhalb von WPF nach c# ziehen. Dies behebt es. IE11 allein erlaubt jedoch definitiv das Ziehen von “Text/Plain”. Gleicher Code im WebBrowser-Steuerelement ist nicht gut. Ich habe nach Einstellungen für das Objekt gesucht, und die gesamten Browser-Funktionseinstellungen sind rigmarole, aber nur das hat funktioniert.

    – Dirk Beste

    25. Juli 2014 um 13:25 Uhr

  • Dies war ein Problem für mich in Safari Webkit beim Erstellen einer GUI mit Java..nette Analyse!.

    – Wiederholungsnull

    8. April 2018 um 3:55 Uhr

Ich weiß, dass Sie dies bereits beantwortet haben, aber dies ist ein nützlicher Thread – ich wollte hier nur einen Nachtrag hinzufügen – wenn Sie die Daten selbst festlegen, können Sie die Daten jederzeit in das Feld selbst einfügen (hässlich, ich weiß). aber es verhindert, dass die Funktionalität neu erstellt werden muss:

Wenn Sie beispielsweise Ihre eigenen benutzerdefinierten Daten festlegen:

  dataTransfer.setData('mycustom/whatever', 'data');

hänge die Daten als neuen Dateneintrag an und iteriere:

  dataTransfer.setData('mycustom/whatever/data/{a json encoded string even}');

abfragen:

// naive webkit only look at the datatransfer.types
if (dataTransfer.types.indexOf('mycustom/whatever') >= 0) {

    var dataTest="mycustom/whatever/data/";

    // loop through types and create a map
    for (var i in types) {

        if (types[i].substr(0, dataTest.length) == dataTest) {

            // shows:
            // {a json encoded string even}
            console.log('data:', types[i].substr(dataTest.length));

            return; // your custom handler
        }
    }
}

nur in Chrom getestet

Beachtenswert ist auch, dass das dataTransfer-Objekt Ihre Daten nicht mehr enthält, wenn Sie die Ausführungskette mit einem Timeout verlassen. z.B

function dropEventHandler(event){
    var dt = event.dataTransfer.getData("text/plain"); // works
    var myEvent = event;

    setTimeout(function(){
       var dt = myEvent.dataTranfer.getData("text/plain"); // null
    }, 1);
}

Benutzer-Avatar
RoshanZ

Ich habe denselben Fehler für den folgenden Code erhalten:

event.originalEvent.dataTransfer.setData(“text/plain”, event.target.getAttribute(‘id’));

Ich habe den Code geändert in:

event.originalEvent.dataTransfer.effectAllowed = “bewegen”; event.originalEvent.dataTransfer.setData(“text”, event.target.getAttribute(‘id’));

Und es hat bei mir funktioniert.

Benutzer-Avatar
Josua España

Ich bin auf diesen Beitrag gestoßen, weil ich ähnliche Erfahrungen mit Chrome gemacht habe dataTransfer.setData() und dataTransfer.getData() Funktionen.

Ich hatte Code, der in etwa so aussah:

HTML:
<div ondragstart="drag(event)" ondrop="newDrop(event)"></div>

JAVASCRIPT:
function drag(ev) {
    ev.dataTransfer.setData("text", ev.target.id);
}
function newDrop(ev){
    var itemDragged = ev.dataTransfer.getData("text");
    var toDropTo = ev.target.id;
}

Der Code funktionierte einwandfrei im Internet Explorer, aber als er in Chrome getestet wurde, konnte ich keine Werte in meinem festlegen dataTransfer Objekt (in Drag-Funktion gesetzt) ​​mit der dataTransfer.getData() Funktion in der newDrop-Funktion. Ich war auch nicht in der Lage, den ID-Wert aus der Anweisung zu erhalten ev.target.id.

Nachdem ich im Web herumgegraben hatte, entdeckte ich, dass ich die Ereignisparameter verwenden sollte currentTarget Eigentum statt Ereignisse target Eigentum. Der aktualisierte Code sah in etwa so aus:

JAVASCRIPT:
function drag(ev) {
    ev.dataTransfer.setData("text", ev.currentTarget.id);
}
function newDrop(ev){
    var itemDragged = ev.dataTransfer.getData("text");
    var toDropTo = ev.currentTarget.id;
}

Mit dieser Änderung konnte ich die verwenden dataTransfer.setData() und dataTransfer.getData() funktioniert sowohl in chrome als auch im internet explorer. Ich habe nirgendwo anders getestet und bin mir nicht sicher, warum das funktioniert hat. Hoffe, das hilft und hoffentlich kann jemand eine Erklärung geben.

1257780cookie-checkHTML5 DnD dataTransfer setData oder getData funktioniert nicht in jedem Browser außer Firefox

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy