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 个带有城市名称的普通 div
s 。因此,在将第一列中的所有可拖动项都放在第二列之后,第二列和第三列的行将产生国家-城市关系。
但问题是在模拟完成后,第一个和第二个可拖动对象被放置在预期的可放置对象上,但第三个可拖动对象只是粘在鼠标上而不是放在可放置对象上。要找到这种行为,在上面提到的 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 列则正常div
s。在拖放模拟之后,第 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 可拖动对象放置在三个可拖放对象之一上时会跳转?