简体   繁体   中英

how to disable a draggable even if dropped into wrong droppable

I know how to disable draggable when the object is dragged into the correct droppable as you can see below but not when dropped into the wrong droppable. I want the user to not be able to drag again even if the answer is incorrect, which means only one try. I use edge animate which uses a different syntax to get the elements than plain JavaScript but the rest is the same. Below is my code with comments.

for(j=0;j<35;j++){
    sym.$(answers1[j]).addClass('drag'+j);
    sym.$('.drag'+j).draggable({
    //revert: "invalid"   // I do not want revert in any case
    stop: function(){
        $(this).draggable('disabled');  // will disable when dropped anywhere
        //I want only when into the wrong droppable - 
        //so almost good but not quite right.
    }           
});

sym.$(droppables[j]).droppable({
    accept: ".drag"+j,
    drop: function(event,ui){
    ui.draggable.draggable( 'destroy' );  // the correct answer is disabled
    //I could have used 'disabled' here since it does the same as 'destroy'.
    } 
});

Basically your problem is that by using both accept and drop option you make the drop execute only for accepted elements.

In order to achieve what you want you'll have to use some other way to define that relation between a draggable and its "correct" droppable .

Eg you could add a data attribute to each droppable that holds the class of the accepted draggable (say data-accept="drag1" ). Then you could remove the accept options from your droppables and in their drop handler manually check if the classes match, something like

drop: function( event, ui ) {
   if (ui.draggable.hasClass( $(this).data('accept') )) { 
        // correct match
   }

   // anyway disable the draggable
   ui.draggable.draggable('disable');
}

Here's a demo: JSFiddle

After getting some clarification, I offer this alternate solution. With multiple answers and places to drop them, when 1 answer is dropped, that should no longer accept answers, and users should not be able to move that answer further.

Working Example: https://jsfiddle.net/Twisty/crdxcg90/3/

HTML

<div>
  <h4>Put the family members in order of youngest to oldest.</h4>
  <p class="drag answer" id="1">Homer</p>
  <p class="drag answer" id="2">Marge</p>
  <p class="drag answer" id="3">Bart</p>
  <p class="drag answer" id="4">Lisa</p>
  <p class="drag answer" id="5">Maggie</p>
</div>

<div class="dropzone drop1" id="drop-1">Youngest</div>
<div class="dropzone drop2" id="drop-2">2</div>
<div class="dropzone drop3" id="drop-3">3</div>
<div class="dropzone drop4" id="drop-4">4</div>
<div class="dropzone drop5" id="drop-5">Oldest</div>

CSS

.drag {
  background: #ccc;
  padding: 3px;
  width: 60px;
  text-align: center;
  margin: 2px;
}

.dropzone {
  width: 100px;
  height: 50px;
  background: #0f0;
  float: left;
  text-align: center;
  margin: 2px;
}

.answered {
  background: #cfc;
}

JQuery

$(function() {
  $(".answer").draggable({
    revert: "invalid"
  });
  $(".dropzone").droppable({
    drop: function(e, ui) {
      $(e.target).addClass("answered");
      ui.draggable.draggable("destroy");
      $(this).droppable("option", "accept", function() {
        return false;
      });
    }
  });
});

You would need to adjust back to your specific assignments, but this may make it easier on you and be more flexible if the number of answers changes often.

Updated

After looking at your sample, I can see more what you're going for. Hopefully this will help you:

https://jsfiddle.net/Twisty/crdxcg90/6/

var answers1 = [1, 3, 5];
var coins = 0;
$(function() {
  $(".answer").draggable({
    revert: "invalid"
  });
  $(".dropzone").droppable({
    drop: function(e, ui) {
      $(e.target).addClass("answered");
      var t = parseInt($(e.target).attr("id").substring(5));
      var a = parseInt(ui.draggable.attr("id"));
      if (answers1[t] === a) {
        $(e.target).addClass("correct");
        coins++;
      }
      ui.draggable.draggable("destroy");
      $(this).droppable("option", "accept", false);
      $("#coins").html(coins);
    },
    tolerance: "fit"
  });
});

When the object is dropped, it checks that position in answers1 if the drop matches the answer, we mark it correct and award a coin.

Here is the final and correct way it was done in Edge Animate. The way to using data() in Edge Animate is a little different than plain javascript and html. We used it in order to be able to compare the data value with the value of the variable ID. We also used one class for the draggables and added the class in the UI for the draggables that did not have a droppable (distractors) so they could still be dragged and placed in a droppable and act as all the other draggables. Then we added the conditional in the dropEvent function.

//'level1-D','level1-E','level1-F'  added the drag class in the UI for distractors.
var answers1 = [
'level1-A','level1-B','level1-C',
'level2-A','level2-B','level2-C',
'level3-A','level3-B','level3-C',
'level4-A','level4-B',
'level5-A','level5-B','level5-C',
'level6-A','level6-B','level6-C',
'level7-A','level7-B','level7-C','level7-D',
'level8-A','level8-B','level8-C','level8-D','level8-E',
'level9-A','level9-B','level9-C',
'level10-A','level10-B','level10-C',
];

var droppables = [
'dp0' ,'dp1' ,'dp2' ,'dp3' ,'dp4' ,'dp5' ,'dp8','dp6','dp7','dp9',
'dp10','dp13','dp11','dp12','dp15','dp16','dp14','dp19','dp17','dp20',
'dp18','dp23','dp22','dp21','dp25','dp24','dp27','dp26','dp28','dp29','dp30','dp31'
];

for(j=0;j<32;j++){
    // draggables
    sym.$(answers1[j]).addClass('drag');
    // droppables
    sym.$(droppables[j]).droppable({
    accept:'.drag',
    drop: dropEvent
    }).data('answer', answers1[j]);  // use data to be able to compare gives the same name as the draggables

}// end for loop
sym.$('.drag').draggable({
        revert : "invalid"      
});

k=0;
function dropEvent(event, ui){
    ui.draggable.draggable('option', 'revert' , false );
    ui.draggable.draggable('option','disabled', true ); 
    ui.draggable.position( { of: $(this), my: 'center', at: 'middle' } );
    ID = ui.draggable.attr("id").replace('Stage_','');
   if(ID == $(this).data('answer')){  // retrieve the data info and compare to ID 
       k++;
        sym.getSymbol("meter").play();
        sym.getSymbol("coinAnimation").play(0); 
        sym.$(ID + '-result').css({'opacity':1.0});
        sym.$("boxScore").html(k);
        sym.$("score").html(k+'/32');
        if (music.paused ) {
            correct.pause();    
        } else {
            correct.currentTime = 0;
            correct.play();
        }
    }// end if
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM