web-dev-qa-db-fra.com

Changer la position des divs avec glisser-déposer jquery

J'essaie de créer un site Web où l'utilisateur peut faire glisser certains éléments (un élément dans div) vers d'autres divs sur la page. Ce n'est pas une table, divise quelque part sur la page.

Avec html5 glisser-déposer, cela fonctionne bien, maintenant j'essaie de le faire pour les appareils mobiles. Je peux faire glisser des éléments vers des divs, les y déposer et bloquer cette dropzone, car un seul élément doit se trouver dans une dropzone. Je peux également faire glisser cet élément vers un autre div ou ailleurs sur la page (les zones de dépôt ne fonctionnent que la première fois qu'un div est supprimé) si j'ai fait une erreur mais je ne peux pas déposer un autre élément dans le div qui est maintenant vide encore.

Comment puis-je réactiver la suppression dans cette Dropzone?

Et est-il possible de changer la position de deux divs si l'un est traîné sur un autre?

Voici la partie pertinente de mon code:

<script type="text/javascript">
$ (init);
function init() {
    $(".dragzones").draggable({
        start: handleDragStart,
        cursor: 'move',
        revert: "invalid",
    });
    $(".dropzones").droppable({
        drop: handleDropEvent,
        tolerance: "touch",              
    });
}
function handleDragStart (event, ui) {}       
function handleDropEvent (event, ui) {
    $(this).droppable('disable');
    ui.draggable.position({of: $(this), my: 'left top', at: 'left top'});
    ui.draggable.draggable('option', 'revert', "invalid");
}
</script>
<body>
<div id="alles">
<div class="dropzones" id="zone1"><div class="dragzones" id="drag1">Item 1</div></div>
<div class="dropzones" id="zone2"><div class="dragzones" id="drag2">Item 2</div></div>
<div class="dropzones" id="zone3"><div class="dragzones" id="drag3">Item 3</div></div>
<div class="dropzones" id="zone4"><div class="dragzones" id="drag4">Item 4</div></div>
    <div class="dropzones" id="zone11"></div>
    <div class="dropzones" id="zone12"></div>
    <div class="dropzones" id="zone13"></div>
    <div class="dropzones" id="zone14"></div>   
</div>
</body>

EDIT: Voici la page qui fonctionne maintenant: Tâche de glisser-déposer

20
Stefan

Voici un exemple de travail: http://jsfiddle.net/Gajotres/zeXuM/

Je pense que tous vos problèmes sont résolus ici.

  • activer/désactiver la suppression des travaux
  • les éléments renvoyés ne les déposent plus sous les autres éléments
  • les éléments retournés ne les masquent plus/les suppriment
  • meilleur positionnement des éléments (il a l'air mieux)
  • il fonctionne sur les appareils mobiles (testé sur Android 4.1.1 Chrome et iPhone)

Voici un code jQuery utilisé:

$(document).on('pageshow', '#index', function(){       
    $(".dragzones").draggable({
        start: handleDragStart,
        cursor: 'move',
        revert: "invalid",
    });
    $(".dropzones").droppable({
        drop: handleDropEvent,
        tolerance: "touch",              
    });
});

function handleDragStart (event, ui) { }

function handleDropEvent (event, ui) {
    if (ui.draggable.element !== undefined) {
        ui.draggable.element.droppable('enable');
    }
    $(this).droppable('disable');
    ui.draggable.position({of: $(this),my: 'left top',at: 'left top'});
    ui.draggable.draggable('option', 'revert', "invalid");
    ui.draggable.element = $(this);
}

    // This is a fix for mobile devices

/iPad|iPhone|Android/.test( navigator.userAgent ) && (function( $ ) {

var proto =  $.ui.mouse.prototype,
_mouseInit = proto._mouseInit;

$.extend( proto, {
    _mouseInit: function() {
        this.element
        .bind( "touchstart." + this.widgetName, $.proxy( this, "_touchStart" ) );
        _mouseInit.apply( this, arguments );
    },

    _touchStart: function( event ) {
         this.element
        .bind( "touchmove." + this.widgetName, $.proxy( this, "_touchMove" ) )
        .bind( "touchend." + this.widgetName, $.proxy( this, "_touchEnd" ) );

        this._modifyEvent( event );

        $( document ).trigger($.Event("mouseup")); //reset mouseHandled flag in ui.mouse
        this._mouseDown( event );

        //return false;           
    },

    _touchMove: function( event ) {
        this._modifyEvent( event );
        this._mouseMove( event );   
    },

    _touchEnd: function( event ) {
        this.element
        .unbind( "touchmove." + this.widgetName )
        .unbind( "touchend." + this.widgetName );
        this._mouseUp( event ); 
    },

    _modifyEvent: function( event ) {
        event.which = 1;
        var target = event.originalEvent.targetTouches[0];
        event.pageX = target.clientX;
        event.pageY = target.clientY;
    }

});

})( jQuery );

L'auteur original d'un plugin touchFix utilisé dans cet exemple est Oleg Slobodskoi .

24
Gajotres

MODIFIÉ:

Sur chaque drop réussi, vous pouvez enregistrer le dernier objet drop sur le draggable. Ainsi, lorsque le objet déplaçable se déplace vers un autre objet déposé, vous pouvez activer le largable du précédent objet déposé.

Voir ci-dessous:

Essayez de modifier le handleDropEvent pour:

function handleDropEvent(event, ui) {
    if (ui.draggable.lastDropObject !== undefined) {
        ui.draggable.lastDropObject.droppable('enable');
    }
    var dropObject = $(this);
    dropObject.droppable('disable');
    ui.draggable.position({
        of: $(this),
        my: 'left top',
        at: 'left top'
    });
    ui.draggable.draggable('option', 'revert', "invalid");
    ui.draggable.lastDropObject = dropObject;
}

Exemple de travail complet basé sur votre code source:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

    <head>
        <title>Drag & Drop with jQuery</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta name="title" content="" />
        <meta name="keywords" content="" />
        <meta name="description" content="" />
        <link href="http://www.didaktik.physik.uni-muenchen.de/forschung/elektronenbahnen/Betaversion/Tests/Styletest.css" rel="stylesheet" type="text/css" />
        <script type="text/javascript" src="http://www.didaktik.physik.uni-muenchen.de/forschung/elektronenbahnen/Betaversion/Tests/../Alle Seiten/JS/jquery.js"></script>
        <script type="text/javascript" src="http://www.didaktik.physik.uni-muenchen.de/forschung/elektronenbahnen/Betaversion/Tests/../Alle Seiten/JS/jquery-ui-1.8.23.custom.min.js"></script>
        <script type="text/javascript" src="http://www.didaktik.physik.uni-muenchen.de/forschung/elektronenbahnen/Betaversion/Tests/../Alle Seiten/JS/jquery.ui.touch-punch.min.js"></script>
        <script type="text/javascript">
            var test;
            $(init);

            function init() {
                $(".dragzones")
                    .draggable({
                    start: handleDragStart,
                    cursor: 'move',
                    revert: "invalid"
                });
                $(".dropzones")
                    .droppable({
                    drop: handleDropEvent,
                    tolerance: "touch",
                });
            };

            function handleDragStart(event, ui) {}

            function handleDropEvent(event, ui) {
                if (ui.draggable.lastDropObject !== undefined) {
                    ui.draggable.lastDropObject.droppable('enable');
                }
                var dropObject = $(this);
                dropObject.droppable('disable');
                ui.draggable.position({
                    of: $(this),
                    my: 'left top',
                    at: 'left top'
                });
                ui.draggable.draggable('option', 'revert', "invalid");
                ui.draggable.lastDropObject = dropObject;
            }



            function check() {
                var i = 1;
                var richtige = 0;
                while (i <= 10) {
                    var j = i + 10;
                    if (document.getElementById('zone' + j)
                        .innerHTML.search('drag' + i + '"') == 27) {
                        document.getElementById('zone' + j)
                            .style.border = '2px solid green';
                        richtige++;
                    } else {
                        document.getElementById('zone' + j)
                            .style.border = '2px solid red';
                    }
                    i++;
                    alert(document.getElementById(zone + j)
                        .innerHTML);
                };
            }
        </script>
    </head>

    <body>
        <div id="alles">
            <div id="hintergrundbildZuordnungsaufgaben">
                <img src="http://www.didaktik.physik.uni-muenchen.de/forschung/elektronenbahnen/Betaversion/Tests/../E-Feld/Bilder/Versuchsaufbau-Elektronenablenkroehre-unbeschriftet.png" width="740">
            </div>
            <div class="dropzones" id="zone1">
                <div class="dragzones" id="drag1">Item 1</div>
            </div>
            <div class="dropzones" id="zone2">
                <div class="dragzones" id="drag2">Item 2</div>
            </div>
            <div class="dropzones" id="zone3">
                <div class="dragzones" id="drag3">Item 3</div>
            </div>
            <div class="dropzones" id="zone4">
                <div class="dragzones" id="drag4">Item 4</div>
            </div>
            <div class="dropzones" id="zone5">
                <div class="dragzones" id="drag5">Item 5</div>
            </div>
            <div class="dropzones" id="zone6">
                <div class="dragzones" id="drag6">Item 6</div>
            </div>
            <div class="dropzones" id="zone7">
                <div class="dragzones" id="drag7">Item 7</div>
            </div>
            <div class="dropzones" id="zone8">
                <div class="dragzones" id="drag8">Item 8</div>
            </div>
            <div class="dropzones" id="zone9">
                <div class="dragzones" id="drag9">Item 9</div>
            </div>
            <div class="dropzones" id="zone10">
                <div class="dragzones" id="drag10">Item 10</div>
            </div>
            <div class="dropzones" id="zone11"></div>
            <div class="dropzones" id="zone12"></div>
            <div class="dropzones" id="zone13"></div>
            <div class="dropzones" id="zone14"></div>
            <div class="dropzones" id="zone15"></div>
            <div class="dropzones" id="zone16"></div>
            <div class="dropzones" id="zone17"></div>
            <div class="dropzones" id="zone18"></div>
            <div class="dropzones" id="zone19"></div>
            <div class="dropzones" id="zone20"></div>
            <button id="check" value="Check" onclick="check()">Check</button>
        </div>
    </body>

</html>

J'espère que ça aide.

Voici ce que j'ai obtenu:

$ (init);
function init() {
    $(".dragzones").draggable({
        start: handleDragStart,
        cursor: 'move',
        revert: 'invalid',
        opacity: .5,
    });
    $(".dropzones").droppable({
        drop: handleDropEvent,
        tolerance: "touch",
        out: handleDropRemove
    });

    //prevents dragging to filled default droppables on start
    $(".dropzones").each(function(){
    if ($(this).html().length) { 
        $(this).addClass('taken'); 
    }
    });
}



function handleDragStart (event, ui) {} 
function handleDropRemove(event, ui) {
        //allows drop after removal
       $(this).removeClass('taken');
}      
function handleDropEvent (event, ui) {
   if ($(this).hasClass('taken')) {
       //rejects drop if full
        ui.draggable.draggable('option', 'revert', true);
    } else {
        //accepts drop if enpty
        ui.draggable.position({of: $(this), my: 'left top', at: 'left top'});
        $(this).addClass('taken');
   }
}

Working Demo Here

Il y a quelques problèmes que j'essaie de trier encore. Il semble que si le curseur touche le bas d'une zone de dépôt lorsqu'elle est remplie, la fonction out est appelée. Je n'arrive pas à comprendre comment empêcher cela.

1
Scott

Votre lien "Exemple" semble fonctionner correctement. Mais je voudrais donner une solution générique à votre problème.

Fondamentalement, vous regardez l'état de dropzone. Lorsque l'utilisateur supprime l'élément, vous vérifiez si la zone de dépôt est disponible ou non. sinon, réglez "revert" sur true.

function handleDropEvent (event, ui) {
    if ($(this).hasClass('occupied')) {
        ui.draggable.draggable('option', 'revert', true);
        return false;
    }
    $(this).append(ui.draggable);
    ui.draggable.position({of: $(this), my: 'left top', at: 'left top'});
    ui.draggable.css('z-index', 0);
    setTimeout(validateDropzones, 0);
}

Un exemple de travail complet est ici: http://jsfiddle.net/jaygiri/SRPm2/

Merci.

1
EGL 2-101