我在页面上有可以用jQuery拖动的元素。这些元素是否具有单击事件,该事件会导航到另一个页面(例如普通链接)。
什么是防止单击引发未拖放状态同时允许其不处于拖放状态的最佳方法?
我对可排序元素有此问题,但认为最好有一种常规拖放的解决方案。
我已经为自己解决了这个问题。之后,我发现Scriptaculous存在相同的解决方案,但也许有人有更好的方法来实现这一目标。
我在页面上有可以用jQuery拖动的元素。这些元素是否具有单击事件,该事件会导航到另一个页面(例如普通链接)。
什么是防止单击引发未拖放状态同时允许其不处于拖放状态的最佳方法?
我对可排序元素有此问题,但认为最好有一种常规拖放的解决方案。
我已经为自己解决了这个问题。之后,我发现Scriptaculous存在相同的解决方案,但也许有人有更好的方法来实现这一目标。
Answers:
一个对我来说很好的解决方案,并且不需要超时:(是的,我有点书呆子;-)
开始拖动时,我向元素添加了一个标记类,例如“ noclick”。放下元素后,将触发click事件-更精确地说,如果拖动结束,则实际上不必将其放到有效目标上。在点击处理程序中,如果存在标记,则删除标记类,否则将正常处理点击。
$('your selector').draggable({
start: function(event, ui) {
$(this).addClass('noclick');
}
});
$('your selector').click(function(event) {
if ($(this).hasClass('noclick')) {
$(this).removeClass('noclick');
}
else {
// actual click event code
}
});
stop: function(event, ui) { $(this).removeClass('noclick'); }
可拖动的处理程序?否则,不会每次拖放都会阻碍下次单击“您的选择器”。
解决方案是添加单击处理程序,以防止单击在拖动开始时传播。然后在执行删除操作后删除该处理程序。最后的动作应该稍微延迟一点,以防止点击的发生。
可排序的解决方案:
...
.sortable({
...
start: function(event, ui) {
ui.item.bind("click.prevent",
function(event) { event.preventDefault(); });
},
stop: function(event, ui) {
setTimeout(function(){ui.item.unbind("click.prevent");}, 300);
}
...
})
可拖动的解决方案:
...
.draggable({
...
start: function(event, ui) {
ui.helper.bind("click.prevent",
function(event) { event.preventDefault(); });
},
stop: function(event, ui) {
setTimeout(function(){ui.helper.unbind("click.prevent");}, 300);
}
...
})
我遇到了同样的问题,尝试了多种方法,但没有一种对我有用。
解决方案1
$('.item').click(function(e)
{
if ( $(this).is('.ui-draggable-dragging') ) return false;
});
对我没有任何帮助。拖动完成后,单击该项目。
解决方案2(由Tom de Boer撰写)
$('.item').draggable(
{
stop: function(event, ui)
{
$( event.originalEvent.target).one('click', function(e){ e.stopImmediatePropagation(); } );
}
});
这工作正常,但在一种情况下失败-当我进入全屏onclick时:
var body = $('body')[0];
req = body.requestFullScreen || body.webkitRequestFullScreen || body.mozRequestFullScreen;
req.call(body);
解决方案3(由Sasha Yanovets撰写)
$('.item').draggable({
start: function(event, ui) {
ui.helper.bind("click.prevent",
function(event) { event.preventDefault(); });
},
stop: function(event, ui) {
setTimeout(function(){ui.helper.unbind("click.prevent");}, 300);
}
})
这对我不起作用。
解决方案4-唯一可行的解决方案
$('.item').draggable(
{
});
$('.item').click(function(e)
{
});
是的,就是这样-正确的顺序就可以了-首先需要绑定draggable()然后单击click()事件。即使将全屏切换代码放入click()事件中,拖动时仍无法全屏显示。适合我!
我真的不喜欢使用计时器或阻止功能,所以我要做的是:
var el, dragged
el = $( '#some_element' );
el.on( 'mousedown', onMouseDown );
el.on( 'mouseup', onMouseUp );
el.draggable( { start: onStartDrag } );
onMouseDown = function( ) {
dragged = false;
}
onMouseUp = function( ) {
if( !dragged ) {
console.log('no drag, normal click')
}
}
onStartDrag = function( ) {
dragged = true;
}
坚如磐石..
lex82的版本,但适用于.sortable()
start: function(event, ui){
ui.item.find('.ui-widget-header').addClass('noclick');
},
并且您可能只需要:
start: function(event, ui){
ui.item.addClass('noclick');
},
这是我用于切换的内容:
$("#datasign-widgets .ui-widget-header").click(function(){
if ($(this).hasClass('noclick')) {
$(this).removeClass('noclick');
}
else {
$(this).next().slideToggle();
$(this).find('.ui-icon').toggleClass("ui-icon-minusthick").toggleClass("ui-icon-plusthick");
}
});
在jQuery UI中,被拖动的元素具有“ ui-draggable-dragging”类。
因此,我们可以使用此类来确定是否单击,只是延迟事件。
您无需使用“开始”或“停止”回调函数,只需执行以下操作:
$('#foo').on('mouseup', function () {
if (! $(this).hasClass('ui-draggable-dragging')) {
// your click function
}
});
这是由“ mouseup”触发的,而不是“ mousedown”或“ click”触发的-因此会有一点延迟,可能并不完美-但比这里建议的其他解决方案更容易。
阅读完本章和一些线程后,这就是我所采用的解决方案。
var dragging = false;
$("#sortable").mouseover(function() {
$(this).parent().sortable({
start: function(event, ui) {
dragging = true;
},
stop: function(event, ui) {
// Update Code here
}
})
});
$("#sortable").click(function(mouseEvent){
if (!dragging) {
alert($(this).attr("id"));
} else {
dragging = false;
}
});
只需一点点皱纹即可添加到上面给出的答案中。我必须使div包含可拖动的SalesForce元素,但是SalesForce元素具有通过一些VisualForce gobbledigook在html中定义的onclick动作。
显然,这违反了“拖动动作后定义单击动作”规则,因此,作为一种解决方法,我将SalesForce元素的动作重新定义为“ onDblClick”,并将此代码用于容器div:
$(this).draggable({
zIndex: 999,
revert: true,
revertDuration: 0,
start: function(event, ui) {
$(this).addClass('noclick');
}
});
$(this).click(function(){
if( $(this).hasClass('noclick'))
{
$(this).removeClass('noclick');
}
else
{
$(this).children(":first").trigger('dblclick');
}
});
父级的click事件本质上隐藏了双击子元素的需求,使用户体验保持完整。
onmousedown和onmouseup事件在我的一个较小的项目中起作用。
var mousePos = [0,0];
function startClick()
{
mousePos = [event.clientX,event.clientY];
}
function endClick()
{
if ( event.clientX != mousePos[0] && event.clientY != mousePos[1] )
{
alert( "DRAG CLICK" );
}
else
{
alert( "CLICK" );
}
}
<img src=".." onmousedown="startClick();" onmouseup="endClick();" />
是的我知道。不是最干净的方法,但是您会明白的。
最简单,最强大的解决方案?只需在您的可拖动对象上创建透明元素即可。
.click-passthrough {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: transparent;
}
element.draggable({
start: function () {
},
drag: function(event, ui) {
// important! if create the 'cover' in start, then you will not see click events at all
if (!element.find('.click-passthrough').length) {
element.append("<div class='click-passthrough'></div>");
}
},
stop: function() {
// remove the cover
element.find('.click-passthrough').remove();
}
});