【问题标题】:how to disable a draggable even if dropped into wrong droppable即使放入错误的可拖放对象,如何禁用可拖动对象
【发布时间】:2016-03-24 15:04:02
【问题描述】:

我知道如何在将对象拖入正确的可拖放对象时禁用可拖动对象,如下所示,但在拖放到错误的可拖放对象时不知道。 我希望用户即使答案不正确也不能再次拖动,这意味着只能尝试一次。 我使用边缘动画,它使用与普通 JavaScript 不同的语法来获取元素,但其余部分相同。 下面是我的 cmets 代码。

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'.
    } 
});

【问题讨论】:

  • 任何一种方式都可以。问题是即使答案不正确也要禁用。当然,现在它通过停止功能禁用舞台上的任何地方。如果没有停止功能,只有当它们处于正确的 droppable 中时,才禁用可拖动对象,这意味着用户可以尝试任何可拖动对象,直到他得到我想要阻止的正确答案。
  • 好的,收到更新了。正确和错误的droppable 有什么区别?你不能以同样的方式处理drop 事件,让它们都禁用可拖动对象吗?
  • 没有。也许我可以解释得更好。我假设 3 个可拖动对象和 3 个可放置对象。每个可拖动对象都被其对应的可放置对象接受。如果我将 .drag1 放在 droppable 1 中,它是正确的并且被禁用并且无法从 droppable 中删除。如果我将 drag1 拖到 droppable 2 中,那么它将继续可拖动,直到将其放入 droppable 1。我想要的是 drag 1 停止可拖动,即使它被放入 droppable 2 或 droppable 3 而不仅仅是 droppable 1。
  • 这意味着无论它是否与 droppable 匹配,它们都应该停止可拖动。还是我又错过了什么? =)
  • 对。不幸的是,如果我使用停止功能,它们在舞台上的任何地方都会被禁用。我希望它们只有在任何可放置的东西中才被禁用,无论是否正确。

标签: javascript jquery jquery-ui jquery-ui-draggable


【解决方案1】:

基本上,您的问题是,通过同时使用 accept 和 drop 选项,您使 drop 仅对接受的元素执行。

为了实现您想要的,您必须使用其他方式来定义 draggable 与其“正确”droppable 之间的关系。

例如您可以为每个包含接受的draggable 的类的droppable 添加一个数据属性(比如data-accept="drag1")。 然后你可以从你的droppables 中删除accept 选项,并在他们的drop 处理程序中手动检查类是否匹配,比如

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

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

这是一个演示:JSFiddle

【讨论】:

  • 这并不能解释为什么 droppable 的 accept 选项无法做到这一点。请进一步解释。
  • 第一句是解释。一旦定义了accept,drop 就不会在其他不被接受的draggables 上执行,这不是所需的行为。相反,无论dragabble 是否被接受,所有droppables 都应该执行相同的drop 处理。这意味着你不能在这里使用accept 机制。
  • 也许我误解了这个问题。我认为 OP 只想接受一个特定的可拖动到特定的 droppable。这样,droppable 只接受拖到它的正确答案。该特定可放置对象不接受所有其他答案。
  • 不,这甚至与接受/匹配无关。这是关于执行相同的操作,无论可拖动对象是否在正确的 droppable 上,同时有办法确定该正确性。
  • 查看作者的第三条评论。
【解决方案2】:

在得到一些澄清后,我提供了这个替代解决方案。有多个答案和放置它们的位置,当删除 1 个答案时,应该不再接受答案,并且用户应该无法进一步移动该答案。

工作示例: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;
      });
    }
  });
});

您需要重新调整到您的具体作业,但如果答案的数量经常变化,这可能会让您更轻松并且更灵活。

更新

查看您的样本后,我可以看到更多您想要的东西。希望这会对您有所帮助:

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

当物体掉落时,它会检查answers1 中的位置,如果掉落与答案相符,我们会将其标记为正确并奖励一枚硬币。

【讨论】:

  • 好的。我会看看我是否能适应我的比赛。我有很多事情要做。我有 10 个问题,拖放次数不同。每次掉落某些东西时,如果掉落正确,则会出现一些动画,如果不正确,则会出现其他动画。同时我有一个正确的分数。所以我仍然需要跟踪什么是正确的并且也有反馈。
  • 我尝试制作一个使用for 循环的程序,但如果您使用类,选择会变得容易得多。如果您可以在 jsfiddle 中创建一个工作示例,请更新您的问题,我们可能会提供进一步的帮助。
  • 顺便说一句,感谢您的回答。我觉得这是一个进步。我希望我可以让它与所有其他人一起工作。 - 我如何检查它是否正确?
  • 我不知道如何使用小提琴,因为它是边缘动画。我在这里发布了示例供您查看:mjpagedesign.com/sample
  • 您的示例将无法正常工作,因为它不允许所有其余的工作。我需要多动脑筋才能完成这项工作。
【解决方案3】:

这是在 Edge Animate 中完成的最终且正确的方法。 在 Edge Animate 中使用 data() 的方式与普通的 javascript 和 html 略有不同。我们使用它是为了能够将数据值与变量 ID 的值进行比较。我们还为可​​拖动对象使用了一个类,并在 UI 中为没有可放置对象(干扰器)的可拖动对象添加了该类,因此它们仍然可以被拖动并放置在可放置对象中并充当所有其他可拖动对象。然后我们在 dropEvent 函数中添加了条件。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多