Предотвратить события click с помощью jQuery и падение


У меня есть элементы на странице, которые draggabe с jQuery. Эти элементы имеют событие click, которое переходит на другую страницу (например, обычные ссылки).

каков наилучший способ предотвратить срабатывание щелчка при сбросе такого элемента, позволяя при этом щелкнуть его в состоянии не перетаскивания?

У меня есть эта проблема с сортируемыми элементами, но думаю, что это хорошо, чтобы иметь решение для общего перетаскивания.

Я решил эту проблему для себя. После что нашел то же решение существует для Scriptaculous, но, возможно, у кого-то есть лучший способ достичь этого.

14 76

14 ответов:

решение, которое хорошо работало для меня, и это не требует тайм-аута: (да, я немного педантичен ; -)

Я добавляю класс маркера к элементу при запуске перетаскивания, например '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
    }
});

решение состоит в том, чтобы добавить обработчик щелчка, который предотвратит распространение щелчка при запуске перетаскивания. А затем удалите этот обработчик после выполнения drop. Последнее действие должно быть отложено немного для предотвращения щелчка, чтобы работать.

решение для сортировки:

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

Я хотел бы добавить к этому, что, похоже, предотвращение события click работает только в том случае, если событие click определено после перетаскиваемого или сортируемого события. Если клик добавляется первым,он активируется при перетаскивании.

у меня была та же проблема, и я попробовал несколько подходов, и ни один не работал для меня.

Решение 1

$('.item').click(function(e)
{            
    if ( $(this).is('.ui-draggable-dragging') ) return false;
});  

ничего не делает для меня. Элемент щелкается после завершения перетаскивания.

решение 2 (Том де Бур)

$('.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 (Саша Яновец)

 $('.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 (), он все равно не перешел в полноэкранный режим при перетаскивании. Идеально подходит для меня!

Я не очень люблю использовать таймеры или предупреждение, так что я сделал это:

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

Rocksolid..

Я обнаружил, что с помощью стандартной функции jQuery click:

$("#element").click(function(mouseEvent){ // click event });

отлично работает в jQuery UI. Событие click не будет выполняться при перетаскивании. :)

версия lex82, но для .сортируемый()

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

возможная альтернатива для ответа Саши без предотвращения дефолта:

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

в пользовательском интерфейсе jQuery перетаскиваемым элементам присваивается класс "ui-draggable-draging".
Поэтому мы можем использовать этот класс, чтобы определить, следует ли щелкнуть или нет, просто задержать событие.
Вам не нужно использовать функции обратного вызова "start" или "stop", просто сделайте:

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

вы пробовали отключить ссылку с помощью события.метод preventDefault(); в начале мероприятия и повторное включение его в перетащите остановил событие или удалить событие, используя отвяжется?

только одно маленькое добавление к ответам выше. Мне пришлось сделать div, который содержит элемент SalesForce draggable, но элемент SalesForce имеет действие onclick, определенное в html через некоторый VisualForce gobbledigook.

очевидно, что это нарушает правило "определить действие щелчка после действия перетаскивания", поэтому в качестве обходного пути я переопределил действие элемента 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 по существу скрывает необходимость двойного щелчка дочернего элемента, оставляя пользовательский интерфейс нетронутым.

Я пробовал так:

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

});

в моем случае это происходило так:

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