JQuery ड्रैग और ड्रॉप के साथ क्लिक इवेंट को रोकना


85

मेरे पास पृष्ठ पर ऐसे तत्व हैं जो jQuery के साथ ड्रैग करने योग्य हैं। क्या इन तत्वों पर क्लिक करने की घटना है जो किसी अन्य पेज (उदाहरण के लिए साधारण लिंक) पर नेविगेट करता है।

ऐसे तत्व को छोड़ने पर क्लिक करने से रोकने के लिए सबसे अच्छा तरीका क्या है जबकि क्लिक करने की अनुमति है कि इसे खींचा नहीं जाए और राज्य छोड़ दिया जाए?

मुझे यह समस्या हल करने वाले तत्वों के साथ है, लेकिन लगता है कि सामान्य ड्रैग और ड्रॉप का समाधान करना अच्छा है।

मैंने अपने लिए समस्या हल कर ली है। उसके बाद मैंने पाया कि वही समाधान Scriptaculous के लिए मौजूद है , लेकिन शायद किसी के पास इसे हासिल करने का एक बेहतर तरीका है।


समान / डुप्लिकेट: stackoverflow.com/questions/3486760/…
रयान

जवाबों:


88

एक समाधान जो मेरे लिए अच्छी तरह से काम करता है और जिसे टाइमआउट की आवश्यकता नहीं है: (हाँ मैं थोड़ा पांडित्यपूर्ण हूं;;

मैं तत्व में एक मार्कर वर्ग जोड़ता हूं जब खींचना शुरू होता है, उदाहरण के लिए '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

2
यह मुझे मेरे समाधान की ओर ले जाता है, मैंने सिर्फ एक वर्ग के बजाय jQuery डेटा फ़ंक्शन का उपयोग किया है। धन्यवाद।
विलियम

3
लेकिन जब भी आप तत्व को
छोड़ते हैं

6
क्लास या डेटा सेट करने के लिए, क्लिक ईवेंट हैंडलर में आप भी उपयोग कर सकते हैं: if ($! (यह) .is ('। Ui-draggable-
draging

1
ओह, क्या आप stop: function(event, ui) { $(this).removeClass('noclick'); }ड्रैग करने योग्य हैंडलर में नहीं आना चाहते हैं ? अन्यथा हर ड्रैग-एन-ड्रॉप कहीं और नहीं होगा 'अपने चयनकर्ता' पर अगला क्लिक करें।
बॉब स्टीन

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 का उपयोग करके im
aaron

1
अजीब है कि आपने अपने प्रश्न का उत्तर दिया, और यह भी काम नहीं कर रहा है, साशा लोल।

@ हारून इस जवाब के नीचे काम करता है: http://stackoverflow.com/a/4572831/119765
lol

एक और सरल उत्तर - बस जगह वें jQuery .click () हैंडलर के बाद .draggable () stackoverflow.com/questions/18032136/...
JxAxMxIxN

1
यदि आप मान 'क्लोन' के साथ विशेषता सहायक को पास करते हैं, तो यह घटना को घसीटे-
छँटे हुए

12

मुझे एक ही समस्या थी और कई तरीकों की कोशिश की और कोई भी मेरे लिए काम नहीं किया।

समाधान 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(); } );
    }
});

यह ठीक काम करता है लेकिन एक मामले में विफल रहता है- जब मैं फुलस्क्रीन पर क्लिक कर रहा था:

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

हां, यह सही है - सही क्रम चाल करता है- पहले आपको ड्रैग करने योग्य () को बांधने की आवश्यकता होती है, फिर क्लिक करें () ईवेंट। यहां तक ​​कि जब मैं फुलस्क्रीन टॉगल कोड को क्लिक () घटना में डाल देता हूं तब भी इसे खींचते समय फुलस्क्रीन पर नहीं जाता था। मेरे लिए सही है!


1
केवल एक जो मेरे लिए काम किया (IE11 / एज में) समाधान 4 था। धन्यवाद!
साइमन

1
# 4 मेरे लिए सही या सरल उपाय है, बिना वर्गों या चर का उपयोग किए।
इलेक्ट्रोटाइप 25

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।
गॉडस्मिथ

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' क्लास को छोड़ सकते हैं और बस कर सकते हैं अगर ($ (यह) .hasClass ('ui-Sortable-helper'))। इस तरह से अधिक कविता
मैट डे लियोन

3

डिफ़ॉल्ट को रोकने के बिना साशा के उत्तर के लिए एक संभावित विकल्प:

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-draging" श्रेणी दी गई है।
इसलिए हम इस वर्ग का उपयोग यह निर्धारित करने के लिए कर सकते हैं कि क्लिक करें या नहीं, बस घटना में देरी करें।
आपको "प्रारंभ" या "स्टॉप" कॉलबैक फ़ंक्शन का उपयोग करने की आवश्यकता नहीं है, बस करें:

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

यह "माउसअप" से शुरू होता है, "मूसडाउन" या "क्लिक" के बजाय - इसलिए इसमें थोड़ी देरी हो सकती है, एकदम सही नहीं हो सकती है - लेकिन यह यहाँ सुझाए गए अन्य समाधानों की तुलना में आसान है।


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

ऊपर दिए गए उत्तरों को जोड़ने के लिए बस एक छोटी सी शिकन। मुझे एक div बनाना था जिसमें SalesForce तत्व को घसीटा जा सकता है, लेकिन SalesForce तत्व को HTML में कुछ VisualForce gobbledigook के माध्यम से परिभाषित किया गया है।

जाहिर है कि यह "ड्रैग एक्शन के बाद परिभाषित क्लिक एक्शन" नियम का उल्लंघन करता है, इसलिए वर्कअराउंड के रूप में मैंने सेल्सफायर एलिमेंट की कार्रवाई को "ऑनडब्लीकक्लिक" के रूप में ट्रिगर किया, और कंटेनर डिव के लिए इस कोड का उपयोग किया:

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

क्लोनिंग डोम तत्व को घसीटा जाता है, जिससे घटना को रोक दिया जाता है। मैं किसी भी घटना के साथ इसे रोक नहीं सकता था, बुदबुदाहट, आदि यह मेरे लिए एकमात्र काम कर रहा समाधान था।


0

मेरी छोटी परियोजनाओं में से एक में ऑन्मसॉउनडाउन और ऑनमाउसअप घटनाओं ने काम किया।

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();
        }
    });
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.