HTML5 Mdn dataTransfer setData ou getData ne fonctionne pas dans tous les navigateurs sauf Firefox

Considérer ce JSFiddle. Il fonctionne bien dans Firefox (14.0.1), mais ne fonctionne pas dans Chrome (21.0.1180.75), Safari (?) et L'Opéra (12.01?) sur Windows (7) et OS X (10.8). Pour autant que je sache, le problème est avec l'un ou l'autre setData() ou getData() méthodes sur l' dataTransfer objet. Voici le code correspondant du 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);
};

autant que je puisse dire cela devrait fonctionner parfaitement et si vous regardez la console en faisant glisser un élément, vous verrez l'id écrit, ce qui veut dire qu'il trouve l'élément très bien et qu'il saisit son attribut id. La question Est de savoir s'il ne s'agit pas simplement de définir les données ou de ne pas les obtenir.

j'apprécierais des suggestions car après une semaine de travail avec trois tentatives et plus de 200 versions, je commence à perdre la tête. Tout ce que je sais, c'est que ça marchait dans la version 60 et que le code spécifique n'a pas changé du tout...

en Fait, l'un des principaux les différences entre 6X et 124 est que j'ai changé la liaison de l'événement de live()on(). Je ne pense pas que ce soit le problème, mais J'en suis venu à voir quelques échecs de Chrome quand il s'agit du MDN tout en travaillant sur ce dossier. ceci a été démystifié. La méthode de l'événement contraignant n'a aucun effet sur la question.

UPDATE

j'ai créé un nouveau JSFiddle qui enlève absolument tout et laisse juste la reliure de l'événement et manipulateur. Je l'ai testé avec jQuery 1.7.2 et 1.8 avec les deux on() et live(). Le problème persistait donc j'ai baissé d'un niveau et j'ai enlevé tous les cadres et utilisé pur JavaScript. La question persisté, donc basé sur mes tests ce n'est pas mon code qui échoue. Au lieu de cela, il apparaît que Chrome, Safari et Opera sont tous implémentés soit setData() ou getData() hors spécifications ou tout simplement l'échec pour une raison ou une autre. S'il vous plaît corrigez-moi si je me trompe.

en tout cas, si vous jetez un oeil au Nouveau JSFiddle vous devriez être en mesure de répliquer le problème, il suffit de regarder la console lorsque vous faites glisser sur un élément désigné pour accepter une goutte. Je suis allé de l'avant et a ouvert un billet avec Chrome. En fin de compte, je fais peut-être encore quelque chose de mal, mais je ne sais pas comment faire autrement le MDN à ce stade. Le nouveau JSFiddle est aussi dépouillé que possible...

34
demandé sur Gup3rSuR4c 2012-08-13 05:44:14

6 réponses

Ok, donc après un peu plus de recherches, j'ai découvert que le problème n'est pas vraiment avec le Chrome, le Safari et L'Opéra. Ce qui l'a donné était que Firefox le supportait et je ne pouvais pas dire que les autres navigateurs sont défaillants, puisque c'est quelque chose que j'accepterais normalement pour IE.

La véritable cause du problème est l' spécification du MDN elle-même. Selon la spécification de l' drag,dragenter,dragleave, dragover et dragend events le mode drag data store est mode protégé. Qu'est-ce que mode protégé demandez-vous? C'est:

Pour tous les autres événements. Les formats et les types dans le drag data store la liste des articles représentant des données traînées peut être énumérée, mais le les données elles-mêmes ne sont pas disponibles et aucune nouvelle donnée ne peut être ajoutée.

cela se traduit par, "vous n'avez pas accès aux données que vous définissez, même pas en mode lecture seule! Allez f@&# vous-même.". Vraiment? Dont la le génie qui a eu cette?

Maintenant, pour contourner cette limitation, vous avez peu de choix, et je ne vais aperçu des deux que j'ai trouvé. Votre premier est d'utiliser une variable globale diabolique et de polluer l'espace de noms global. Votre deuxième choix est d'utiliser L'API HTML5 localStorage pour effectuer exactement la même fonctionnalité que l'API Mdn aurait dû fournir pour commencer!

si vous suivez cette voie, ce que j'ai fait, vous mettez maintenant en place deux API HTML5 Non parce que vous voulez, mais parce que vous . Maintenant je commence à apprécier!--31-- > l'engouement de PPK pour le désastre que l'API HTML5 du MDN est.

La ligne de fond est cela, la spécification doit être modifié pour permettre l'accès aux données stockées, même si c'est seulement en mode lecture seule. Dans mon cas, avec ce JSFiddle, j'utilise le dragenter comme un moyen de regarder vers l'avant à la zone de largage et de vérifier que je devrais permettre une se produire ou pas.

Dans ce cas, Mozilla apparemment choisi de pleine conformité avec la spécification qui est pourquoi mon JSFiddle a été fonctionne correctement. Il se trouve que c'est la seule fois que je soutiens totalement le fait de ne pas soutenir la spécification complète.

63
répondu Gup3rSuR4c 2012-08-14 19:43:22

Il y a une raison pour la "protégés"....glisser / déposer peut couvrir des fenêtres complètement différentes, et ils ne voulaient pas que quelqu'un soit en mesure de mettre en œuvre un DIV "auditeur" qui écouterait sur le contenu de tout ce qui a été traîné sur elle (et peut-être envoyer ces contenus par AJAX à un serveur espion à Elbonia). Seule la zone de largage (qui est plus clairement sous le contrôle de l'utilisateur) obtient le scoop complet.

Ennuyeux, mais je peux voir pourquoi il pourrait être nécessaire.

15
répondu Jens Fiederer 2013-03-15 19:30:13
var dragStartHandler = function (e) {
    e.originalEvent.dataTransfer.effectAllowed = "move";
    e.originalEvent.dataTransfer.setData("text/plain", this.id);
};

Le problème est avec le "text/plain". La spécification standard dans la documentation MSDN pour setData est simplement "text" (sans le /plain). Chrome accepte le / plain, mais pas IE, dans toutes les versions que j'ai essayées.

j'ai lutté avec le même problème pendant plusieurs semaines, en essayant de comprendre pourquoi mes événements "drop" ne fonctionnaient pas correctement dans IE alors qu'ils le faisaient dans CHrome. C'était parce que les données de transfert de données n'avaient pas été correctement chargées.

12
répondu Roland 2013-12-03 06:35:36

je sais que vous avez déjà répondu à cette question, mais c'est un bon thread -- je voulais juste ajouter un additif ici-si vous organisez vous-même vos données, vous pouvez toujours ajouter les données dans le champ lui-même (moche je sais), mais il évite d'avoir à re-créer une fonctionnalité:

par exemple, si vous définissez vos propres données personnalisées:

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

ajouter les données dans une nouvelle entrée de données, et l'itération:

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

requête:

// 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
        }
    }
}

testé dans chrome seulement

5
répondu ansiart 2012-12-28 21:48:30

il est également intéressant de noter que si vous quittez la chaîne d'exécution en utilisant un timeout, l'objet dataTransfer n'aura plus vos données. par exemple,

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);
}
2
répondu Nate Bosscher 2015-06-26 12:56:12

j'ai été faire la même erreur pour le code ci-dessous:

événement.originalEvent.dataTransfer.setData ("text / plain", événement.cible.getAttribute ('id'));

j'ai changé le code en:

événement.originalEvent.dataTransfer.effectAllowed = "déplacer"; événement.originalEvent.dataTransfer.setData("texte", un événement.cible.getAttribute ('id'));

et ça a marché pour moi.

1
répondu RoshanZ 2016-02-19 06:12:06