jQuery 드래그 앤 드롭으로 클릭 이벤트 방지


86

페이지에 jQuery로 드래그 할 수있는 요소가 있습니다. 이러한 요소에 다른 페이지 (예 : 일반 링크)로 이동하는 클릭 이벤트가 있습니까?

드래그 앤 드롭 상태가 아닌 클릭을 허용하면서 이러한 요소를 놓을 때 클릭이 발생하지 않도록하는 가장 좋은 방법은 무엇입니까?

나는 정렬 가능한 요소 에이 문제가 있지만 일반적인 드래그 앤 드롭에 대한 해결책을 갖는 것이 좋다고 생각합니다.

나는 스스로 문제를 해결했다. 그 후 Scriptaculous대해 동일한 솔루션 이 존재 한다는 것을 발견 했지만 누군가이를 달성하는 더 좋은 방법이있을 수 있습니다.


답변:


89

나를 위해 잘 작동하고 시간 초과가 필요하지 않은 솔루션 : (예, 약간 현학적입니다 ;-)

드래그가 시작될 때 요소에 마커 클래스를 추가합니다 (예 : 'noclick'). 요소가 드롭되면 클릭 이벤트가 트리거됩니다.보다 정확하게는 드래그가 끝나면 실제로 유효한 타겟에 드롭 할 필요가 없습니다. 클릭 핸들러에서 마커 클래스가 있으면 제거하고 그렇지 않으면 클릭이 정상적으로 처리됩니다.

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

1
유능한! 한 번에 저를 위해 일하지 않았습니다. 아마도 이전 시도에서 같은 일을 엉망으로 만들고 클래스가 클릭 한 것과 다른 요소에서 끝났기 때문일 것입니다. 그러나 어쨌든 전역 변수를 사용했습니다 (이것은 매우 간단한 페이지도 괜찮 았습니다), 그것도 아주 잘 작동했습니다.
MSpreij 2010

2
이것은 저를 내 솔루션으로 이끌고 클래스 대신 jQuery 데이터 함수를 사용했습니다. 감사.
William

3
하지만 브라우저 늘 트리거 클릭 이벤트 때마다 당신은 요소 드롭
puchu

6
클래스 또는 데이터 설정을 저장하려면 클릭 이벤트 핸들러에서 다음을 사용할 수도 있습니다. if (! $ (this) .is ( '. ui-draggable-dragging')) {... click action}
ChrisV

1
웁스, stop: function(event, ui) { $(this).removeClass('noclick'); }드래그 가능한 핸들러 를 원하지 않습니까? 그렇지 않으면 다른 곳에서 모든 드래그 앤 드롭이 '선택자'를 클릭하는 것을 방해하지 않습니다.
Bob Stein

41

해결책은 드래그 시작시 클릭이 전파되는 것을 방지하는 클릭 핸들러를 추가하는 것입니다. 그리고 드롭이 수행 된 후 해당 핸들러를 제거하십시오. 클릭 방지가 작동하려면 마지막 작업이 약간 지연되어야합니다.

정렬 가능한 솔루션 :

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

2
이것이 나를 위해 클릭 이벤트를 막을 수없는 것 같습니다. jquery 1.9.1 및 jquery.ui 1.10.3을 사용하는 메신저
aaron

1
자신의 질문에 답한 것이 이상하지만 작동하지 않습니다, Sasha lol.

@aaron이 대답은 아래에서 작동합니다. http://stackoverflow.com/a/4572831/119765
lol

또 다른 간단한 대답-jQuery .click () 핸들러를 .draggable () 뒤에 배치하십시오. stackoverflow.com/questions/18032136/…
JxAxMxIxN

1
값이 'clone'인 속성 도우미를 전달하면 드래그 된 정렬 된 항목에 이벤트가 트리거되는 것을 방지합니다. {helper : 'clone', start, stop ... etc},
Luchux

12

나는 같은 문제가 있었고 여러 접근법을 시도했지만 아무도 나를 위해 일하지 않았습니다.

해결 방법 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(); } );
    }
});

이것은 잘 작동하지만 한 가지 경우에 실패합니다.

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 () 이벤트에 전체 화면 토글 코드를 입력해도 드래그 할 때 전체 화면으로 이동하지 않았습니다. 나 한테 딱이야!


1
나를 위해 일한 유일한 솔루션 (IE11 / Edge)은 솔루션 4였습니다. 감사합니다!
Simon

1
# 4는 클래스 나 변수를 사용하지 않는 가장 정확하고 간단한 솔루션입니다.
electrotype

11

클릭 이벤트가 드래그 가능하거나 정렬 가능한 이벤트 이후에 정의 된 경우에만 클릭 이벤트가 작동하지 않는 것 같다고 여기에 추가하고 싶습니다. 클릭이 먼저 추가되면 드래그시 활성화됩니다.


9

나는 타이머를 사용하거나 방지하는 것을 정말로 좋아하지 않으므로 내가 한 일은 다음과 같습니다.

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

바위처럼 단단한..


이것은 나에게 가장 좋은 해결책이었습니다. jquery.ui.touch.punch.js를 사용하여 모바일 웹 브라우저에서 정렬 가능한 jquery UI에서 클릭 이벤트가 작동하도록하는 데 문제가 있었지만 이로 인해 상당히 우아하게 해결되었습니다.
Godsmith

3

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

2
jquery UI가 정렬중인 항목에 'ui-sortable-helper'클래스를 추가하는 것으로 보입니다. 따라서 'noclick'클래스를 생략하고 if ($ (this) .hasClass ( 'ui-sortable-helper')) 만 수행 할 수 있습니다. 더 간결한 방법
Matt De Leon

3

기본값을 방지하지 않고 Sasha의 대답에 대한 가능한 대안 :

var tmp_handler;
.sortable({
        start : function(event,ui){
            tmp_handler = ui.item.data("events").click[0].handler;
            ui.item.off();
        },
        stop : function(event,ui){
            setTimeout(function(){ui.item.on("click", tmp_handler)}, 300);
        },

3

jQuery UI에서 드래그되는 요소에는 "ui-draggable-dragging"클래스가 지정됩니다.
따라서이 클래스를 사용하여 클릭할지 여부를 결정하고 이벤트를 지연시킬 수 있습니다.
"start"또는 "stop"콜백 함수를 사용할 필요가 없습니다. 다음과 같이하면됩니다.

$('#foo').on('mouseup', function () {
    if (! $(this).hasClass('ui-draggable-dragging')) {
        // your click function
    }
});

이것은 "mousedown"또는 "click"이 아닌 "mouseup"에서 트리거되므로 약간의 지연이 있고 완벽하지 않을 수 있지만 여기에 제안 된 다른 솔루션보다 쉽습니다.


1

이것과 몇 개의 스레드를 읽은 후 이것이 내가 함께 갔던 해결책이었습니다.

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

1

제 경우에는 다음과 같이 작동했습니다.

$('#draggable').draggable({
  start: function(event, ui) {
    $(event.toElement).one('click', function(e) { e.stopPropagation(); });
  }
});

0

event.preventDefault ();를 사용하여 링크를 비활성화 해 보셨습니까? 시작 이벤트에서 드래그 중지 이벤트 또는 바인딩 해제를 사용하여 드롭 이벤트에서 다시 활성화 하시겠습니까?


0

위에 주어진 답변에 약간의 주름을 추가하십시오. 드래그 가능한 SalesForce 요소가 포함 된 div를 만들어야했지만 SalesForce 요소에는 VisualForce gobbledigook을 통해 HTML에 정의 된 onclick 작업이 있습니다.

분명히 이것은 "끌기 동작 후 클릭 동작 정의"규칙을 위반하므로 해결 방법으로 "onDblClick"이 트리거되도록 SalesForce 요소의 동작을 재정의하고 컨테이너 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');
    }
});

부모의 클릭 이벤트는 기본적으로 자식 요소를 두 번 클릭 할 필요를 숨기고 사용자 경험은 그대로 둡니다.


0

나는 이렇게 시도했다 :

var dragging = true; 

$(this).click(function(){
  if(!dragging){
    do str...
  }
});

$(this).draggable({
  start: function(event, ui) {
      dragging = true;
  },

  stop: function(event, ui) {
      setTimeout(function(){dragging = false;}, 300);
  }

});

0

나를 위해 옵션 개체의 도우미를 다음과 같이 전달하는 데 도움이되었습니다.

.sortable({
   helper : 'clone', 
   start:function(), 
   stop:function(),
   .....
});

드래그 된 dom 요소를 복제하여 이벤트의 버블 링을 방지 한 것 같습니다. eventPropagation, 버블 링 등으로 피할 수 없었습니다. 이것이 저에게 유일한 해결책이었습니다.


0

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();" />

네, 알아요. 가장 깨끗한 방법은 아니지만 아이디어를 얻습니다.


0

가장 쉽고 강력한 솔루션? 드래그 가능한 위에 투명한 요소를 만드십시오.

.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();
        }
    });
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.