Предотвратить события click с помощью jQuery и падение
У меня есть элементы на странице, которые draggabe с jQuery. Эти элементы имеют событие click, которое переходит на другую страницу (например, обычные ссылки).
каков наилучший способ предотвратить срабатывание щелчка при сбросе такого элемента, позволяя при этом щелкнуть его в состоянии не перетаскивания?
У меня есть эта проблема с сортируемыми элементами, но думаю, что это хорошо, чтобы иметь решение для общего перетаскивания.
Я решил эту проблему для себя. После что нашел то же решение существует для Scriptaculous, но, возможно, у кого-то есть лучший способ достичь этого.
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 по существу скрывает необходимость двойного щелчка дочернего элемента, оставляя пользовательский интерфейс нетронутым.