jQuery 拖放模拟对最后一个可拖动对象不起作用

Posted

技术标签:

【中文标题】jQuery 拖放模拟对最后一个可拖动对象不起作用【英文标题】:jQuery drag and drop simulation does not work for the last draggable 【发布时间】:2019-06-27 03:27:44 【问题描述】:

我正在尝试使用jquery-ui的jquery-simulate-ext插件模拟拖放模拟。

在我给出场景的细节之前,让我给你看一下js小提琴here。

我有 3 列 divs。在第一列中,我有 3 个带有国家名称的可拖动对象,在第二列中有 3 个空白 divs 的 droppables,在第三列中,有 3 个带有城市名称的普通 divs 。因此,在将第一列中的所有可拖动项都放在第二列之后,第二列和第三列的行将产生国家-城市关系。

但问题是在模拟完成后,第一个和第二个可拖动对象被放置在预期的可放置对象上,但第三个可拖动对象只是粘在鼠标上而不是放在可放置对象上。要找到这种行为,在上面提到的 js fiddle 页面加载后,只需将鼠标光标移动到结果部分,您就会看到一个可拖动的对象也随着鼠标移动。您必须单击某处才能使可拖动部分位于可放置或可拖动部分(取决于您单击的区域)。这仅在 Firefox 中发生,而 在 chrome 中,可拖动对象仅在适当的可放置部分内随光标移动,然后自动位于该部分内。

我想要的是: 与其他可拖动对象一样,第三个可拖动对象不应随着鼠标的移动而移动,而应自动位于所需的可拖放对象上。

代码说明:

每个类draggable_div 的可拖动div 都有一个属性data-index(值1、2、3 等)。可放置的 divs (with class droppable_blank) 也是如此。现在在 JS 代码的开头,我有一行:

answers_found='[1,2,3]';

这些基本上是来自可拖动对象的data-index 值。值的顺序仅显示可拖放对象的data-index 值在它们位于可放置对象上时的顺序。在上述情况下,第一个值是 1,因此它将是第一个(不是第二个或第三个)可拖动对象,它将位于第一个 droppable 上。同样,第 2 和第 3 个可拖动对象将连续位于第 2 个和第 3 个可放置对象上。

代码执行如下for循环

for(var i =0; i<answers_found.length; i++)

answers_found 数组中获取每个值。该值是可拖动的data-index 属性值。然后call_trigger_drop 函数被赋予 2 个参数:

call_trigger_drop(parseInt(answer_found_indiv),droppable_index);

第一个是可拖动索引,第二个是对应可拖放索引,即可拖动将位于可拖放索引上。然后使用以下几行进行实际模拟:

draggable.simulate("drag", 
                dx: dx,
                dy: dy
            );

TL;DR:

第 1 列的 Draggables 被模拟为拖放到第 2 列的 droppables 上,而第 3 列则正常divs。在拖放模拟之后,第 3 个可拖动对象不在 Firefox 中的第 3 个可拖放对象上,而是随着光标移动,直到发生单击。 如何让它像其他可拖动对象一样自动放在 droppable 上?

编辑: 如果你想得到一个普通网页而不是 js-fiddle 的结果,你可以找到here。

console = ;
console.log = function();
window.console = console;
drag_stop_counter = 0;
answers_found = '[3,2,1]';
answer_all_zero = 0; //REMOVABLE
if (answers_found != "".trim()) 
  answers_found = $.parseJSON(answers_found);
  answer_all_zero = 1;
  for (var i = 0; i < answers_found.length; i++) 
    if (parseInt(answers_found[i]) != 0) 
      answer_all_zero = 0;
      break;
    
   //end of for loop

total_answers_found = answers_found.length;
total_actual_answers_found = 0;
for (var i = 0; i < answers_found.length; i++) 
  if (parseInt(answers_found[i])) 
    ++total_actual_answers_found;
  
 //end of for loop
answers = [];
answers_made_for_insert = [];
question_id = 2901;
//Following function is triggered
//when the dNd component is starting the drop
//event
function trigger_drop(draggable_elem_index, droppable_elem_index) 
  if (draggable_elem_index && droppable_elem_index) 
    if (window.console) 
      console.log("from within trigger_drop : draggable_elem_index = " + draggable_elem_index + " droppable_elem_index=  " + droppable_elem_index);
    
    // var draggable = $(".draggable_container_indiv .draggable_div").eq(draggable_elem_index-1).draggable(),
    var draggable = $(".draggable_container_indiv").eq(draggable_elem_index - 1).find(".draggable_div").draggable(),
      droppable = $("#droppable_slots .droppable_blank").eq(droppable_elem_index - 1).droppable(),
      droppableOffset = droppable.offset(),
      draggableOffset = draggable.offset(),
      dx = droppableOffset.left - draggableOffset.left,
      dy = droppableOffset.top - draggableOffset.top;
    draggable.simulate("drag", 
      dx: dx,
      dy: dy
    );
   // end of if(draggable_elem_index && droppable_elem_index)
 // end of function trigger_drop(

//answers stored in array for insertion in DB
function make_answers_for_insert(answer_given) 
  answers_made_for_insert.push(answer_given);
 //end of function answers_for_insert
//finds answers from array
function find_answers() 
  answers = [];
  $('input[name="' + question_id + '[]"]').each(function() 
    $elem = $(this);
    var value_found = $elem.val().trim();
    if (value_found == "".trim()) 
      value_found = "0";
    
    // if(value_found!="".trim())
    answers.push(value_found);
    // 
  );
  //alert("answers made "+answers);
  if (window.console) 
    console.log("answers from find_answers = ");
    console.log(answers);
  
 //end of function find_answers

function call_trigger_drop(answer_found_indiv, droppable_index) 
  trigger_drop(answer_found_indiv, droppable_index);

function insert_answer() 
  if (window.console) 
    console.log(" can_submit in insert_answer = " + can_submit);
  
  if (can_submit) 
    can_submit = 0
    $("#draggable .draggable_div").draggable('disable');
    //ui.draggable.draggable(disabled: true);
    $('#droppable_slots li').find('.ui-draggable').draggable(
      disabled: true
    );
    answers = [];
    $('input[name="' + question_id + '[]"]').each(function() 
      $elem = $(this);
      var value_found = $elem.val().trim();
      if (value_found == "".trim()) 
        value_found = "0";
      
      // if(value_found!="".trim())
      answers.push(value_found);
      // 
    );
    answers = JSON.stringify(answers);
    if (window.console) 
      console.log("answers from insert_answers = ");
      console.log(answers);
    
    //ajax call for insertion
   // end of if(can_submit)
 // end of function insert_anwers
$(document).ready(function() 
  answer_status = 0;
  review_table_status = 0;
  $('input[name="' + question_id + '[]"]').each(function() 
    var dnd_value_found = $(this).val().trim();
    if (window.console) 
      console.log(" dnd_value_found = " + dnd_value_found);
    
    if (dnd_value_found != "".trim()) 

      answer_status = 1;
      review_table_status = 1;
      return false;
    
  ); // end of each
  var draggable_counter = 0;
  $(".draggable_container_indiv").each(function() 
    // $draggable_elem=$(this);
    $draggable_elem = $(".draggable_div").eq(draggable_counter);
    var $droppable_elem = $(".droppable_content_indiv").eq(draggable_counter);
    var $draggable_container_indiv_elem = $(".draggable_container_indiv").eq(draggable_counter);
    var $droppable_blank_elem = $(".droppable_blank").eq(draggable_counter);
    var droppable_height = $droppable_elem.css('height');
    var draggable_height = $draggable_elem.css('height');
    var droppable_width = $droppable_elem.css('width');
    var draggable_width = $draggable_elem.css('width');
    var height_more = 0;
    if (parseInt(draggable_height) > parseInt(droppable_height)) 
      height_more = draggable_height;
     else 
      height_more = droppable_height;
    
    var width_more = 0;
    if (parseInt(draggable_width) > parseInt(droppable_width)) 

      width_more = draggable_width;

     else 
      width_more = droppable_width;
    

    if (window.console) 

      console.log(" draggable_height " + draggable_height + " droppable_height = " + droppable_height + " height_more = " + height_more);

    
    $draggable_elem.css(
      'height': height_more
    );
    $droppable_elem.css(
      'height': height_more
    );
    $droppable_blank_elem.css(
      'height': height_more
    );
    $draggable_container_indiv_elem.css(
      'height': height_more
    );
    //$('.draggable_container_indiv').css('height':22);// hhhhhhhh

    $draggable_elem.css(
      'width': width_more
    );
    $droppable_elem.css(
      'width': width_more
    );
    $droppable_blank_elem.css(
      'width': width_more
    );
    $draggable_container_indiv_elem.css(
      'width': width_more
    );
    $droppable_elem.find(".ui-draggable").css(
      'width': width_more
    );


    ++draggable_counter;



  );


  $("#draggable .draggable_div").draggable(
    scroll: false,
    revert: true,
    // helper: 'clone',
    //appendTo: 'body',
    start: function() 

      if (window.console) 

        console.log(" draggable started ....... ");
      

      $(this).css(
        display: 'none'
      );


    ,
    stop: function() 


      $(this).css(
        display: 'block'
      );
      var draggableIndex = $(this).data('index');
      ++drag_stop_counter;
      if (window.console) 

        console.log(" draggable stopped = " + drag_stop_counter);

        console.log("draggable index in stop = " + draggableIndex);

      


      var droppableIndex = $('#droppable_slots li').find('.ui-draggable[data-index=' + draggableIndex + ']').closest('.slot').data('index');

      var index_found = $.inArray(draggableIndex + "", answers);

      if (window.console) 
        console.log("inside stop  draggableIndex = " + draggableIndex + " after dropped ..... index_found = " + index_found);

      



    ,
    revert: function(dropped) 


      var dropped = dropped && dropped.hasClass('slot'); //fix duplicated IDs
      if (!dropped) 
        $(this).appendTo($(this).data('originalParent'))
      
      return !dropped;


    ,
    revertDuration: 0, //removed glitched effect
    helper: function() 
      return $(this).clone().appendTo('body').show();
    ,
    containment: '.sel_screen_left'
  ).each(function() 
    $(this).data('originalParent', $(this).parent())
  );


  $("#droppable_slots li").droppable(
    //        tolerance:'pointer',
    tolerance: 'intersect',
    drop: function(event, ui) 

      $(this).trigger('dropthis', [event, ui]); //REMOVABLE

      $(this).trigger("dropthis", [, 
        draggable: ui.draggable
      ]); //REMOVABLE



      var $this = $(this);
      if ($this.find('.ui-draggable').length) return; //don't overwrite occupied spot
      //$this.empty();
      $this.append(ui.draggable);

      var width = $this.width();
      var height = $this.height();
      var cntrLeft = (width / 2) - (ui.draggable.width() / 2);
      var cntrTop = (height / 2) - (ui.draggable.height() / 2);

      ui.draggable.css(
        left: cntrLeft + "px",
        top: cntrTop + "px"
      );

      var draggableIndex = parseInt(ui.draggable.data("index"));
      var droppableIndex = parseInt($(this).data("index"));

      if (window.console) 

        console.log(" draggableIndex = " + draggableIndex + " droppableIndex = " + droppableIndex + " question_id = " + question_id);

      


      if (window.console) 
        console.log("droppable question_id = " + question_id);
        console.log(" droppable drop has  draggableIndex answer  = " + draggableIndex);

      




      if (window.console) 
        console.log(" inside drop .......................... ");

      


      var index_found = $.inArray(draggableIndex + "", answers);

      if (window.console) 
        console.log(" draggableIndex = " + draggableIndex + " after dropped ..... index_found = " + index_found);

      
      if (index_found != -1) 
        answers[index_found] = '';

        $('input[name="' + question_id + '[]"]').eq(index_found).val('');
      






      $(".droppable_blank[data-index=" + droppableIndex + "]").trigger('click');

      if (window.console) 
        console.log(" droppable_blank clicked   droppableIndex = " + droppableIndex);

      



    ,
    out: function(event, ui) 


    ,
    over: function(event, ui) 

    
  );



  if (window.console) 

    console.log("DnD ANSWERS  found = ");
    console.log(answers_found);

  


  answer_found_indiv = 0;
  droppable_index = 0;
  for (var i = 0; i < answers_found.length; i++) 

    //return false;

    if (window.console) 

      console.log(" iterating all answers:  DnDDnDDnDDnDDnD dragndrop draggable index = " + answers_found[i] + " droppable index = " + (i + 1));

    

    var droppable_index = i + 1;
    var answer_found_indiv = parseInt(answers_found[i]);
    if (answer_found_indiv == 0) 

      if (window.console) 

        console.log(" answer_found_indiv 000000000000000000");

      

     else if (answer_found_indiv) 

      if (window.console) 

        console.log("Trigger Drop = " + answer_found_indiv, " droppable_index = " + droppable_index);

      

      call_trigger_drop(parseInt(answer_found_indiv), droppable_index);

    



   // end of for loop




);
.noselect 
    -webkit-touch-callout: none; /* ios Safari */
    -webkit-user-select: none; /* Safari */
    -khtml-user-select: none; /* Konqueror HTML */
    -moz-user-select: none; /* Firefox */
    -ms-user-select: none; /* Internet Explorer/Edge */
    user-select: none; /* Non-prefixed version, currently
                                  supported by Chrome and Opera */


.draggable_container_indiv

    border: 1px solid green;



#draggable .draggable_div 
    margin-left: -60px;
    padding: 10px;

.droppable_blank
    /*line-height: 40px;*/
    vertical-align: middle;

#draggable li, #draggable .draggable_div, #droppable_slots li, .draggable_div
    list-style: none;

.dragndrop-questions ul.option-left li
    padding-top: 0;

.match-questions ul.option-left li, .dragndrop-questions ul.option-left li
    font-size: 14px;
    color: #656f7d;
    position: relative;
    padding-left: 60px;
    min-height: 40px;


.draggable_container_indiv

    margin-bottom: -10px !important;
<link href="https://epractice.lcbsdhaka.com/mytest/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://epractice.lcbsdhaka.com/mytest/js/jquery-ui-1.12.1.custom/jquery-ui.css"></link>
    <script src="https://epractice.lcbsdhaka.com/mytest/js/jquery-1.12.4.js"></script>


    <script src="https://epractice.lcbsdhaka.com/mytest/js/jquery-ui-1.12.1.custom/jquery-ui.min.js"></script>

    <script src="https://epractice.lcbsdhaka.com/mytest/js/bootstrap.min.js"></script>

    <script src="https://epractice.lcbsdhaka.com/mytest/js/jquery.simulate.js"></script>
    <script src="https://epractice.lcbsdhaka.com/mytest/js/jquery-simulate-ext/src/jquery.simulate.ext.js"></script>
    <script src="https://epractice.lcbsdhaka.com/mytest/js/jquery-simulate-ext/src/jquery.simulate.drag-n-drop.js"></script>


<script src="https://epractice.lcbsdhaka.com/mytest/js/bootstrap.min.js"></script>

<script src="https://epractice.lcbsdhaka.com/mytest/js/jquery-ui-1.12.1.custom/jquery-ui.min.js"></script>



<div class="dragndrop-questions row">



  <div>
    <div style="width:30%; float: left; ">
      <ul class="option option-left" id="draggable">

        <li  class="draggable_container_indiv noselect">
          <div class="draggable_div" data-index="1">

            USA
          </div>
        </li>

        <li  class="draggable_container_indiv noselect">
          <div class="draggable_div" data-index="2">

            JAPAN
          </div>
        </li>

        <li  class="draggable_container_indiv noselect">
          <div class="draggable_div" data-index="3">

            CHINA
          </div>
        </li>

      </ul>
    </div>
    <div  style="width:65%; float: right; margin-right: 10px;">
      <ul class="option option-right" id="droppable_slots">


        <div class="row ">
          <div style="width:45%; float: left; margin-left:10px; border: 1px solid red;">

            <li class="slot droppable_blank noselect" data-index="1">


            </li>

          </div>
          <div style="width:48%; float: right; border: 1px solid yellow;">


            <li class="droppable_content_indiv noselect">
              <p>
                NewYork
              </p>


            </li>
          </div>
        </div>
        <!--end of class row -->

        <div class="row ">
          <div style="width:45%; float: left; margin-left:10px; border: 1px solid red;">

            <li class="slot droppable_blank noselect" data-index="2">


            </li>

          </div>
          <div style="width:48%; float: right; border: 1px solid yellow;">


            <li class="droppable_content_indiv noselect">
              <p>
                Tokyo
              </p>

            </li>
          </div>
        </div>
        <!--end of class row -->


        <div class="row ">
          <div style="width:45%; float: left; margin-left:10px; border: 1px solid red;">

            <li class="slot droppable_blank noselect" data-index="3">


            </li>

          </div>
          <div style="width:48%; float: right; border: 1px solid yellow;">


            <li class="droppable_content_indiv noselect">
              <p>
                Beijing
              </p>

            </li>
          </div>
        </div>
        <!--end of class row -->




      </ul>
    </div>

    <div class="" style="clear: both;"></div>
  </div>


</div>
<!-- end of class dragndrop-questions-->

【问题讨论】:

【参考方案1】:

因为它只模拟drag事件而没有drop,所以改用drag-n-drop

draggable.simulate("drag-n-drop", dx: dx,  dy: dy);

【讨论】:

其他的可拖动对象怎么会落在预期的可拖放对象上? 这是因为你不能拖动多个元素,所以如果你拖动另一个元素,之前拖动的元素将被取消或丢弃。 在 jQuery-ui 文档中是在哪里说的? 我说的是simulate 插件而不是jQuery-ui。它不是来自文档,但这是我从这个插件的工作原理中看到的。

以上是关于jQuery 拖放模拟对最后一个可拖动对象不起作用的主要内容,如果未能解决你的问题,请参考以下文章

jQuery UI droppable:悬停时调整元素大小不起作用

具有可拖放可拖动和可调整大小的 Jquery 无法按预期工作

jQuery-UI:即使鼠标在放置区域内,拖放有时也不起作用

为啥我的 Jquery 可拖动对象放置在三个可拖放对象之一上时会跳转?

将可拖动对象放入可排序对象后,jQuery Click 事件不起作用

使用 JQuery“模拟”拖放的简单方法?