23

मैं jQuery droppable (jQuery draggable के साथ संयोजन में) का उपयोग कर रहा हूं ताकि उपयोगकर्ता किसी सूची में आइटम्स खींचकर उन्हें छोड़कर HTML तालिका में पंक्तियां जोड़ सकें। टेबल।jQuery ड्रॉपपैबल - ड्रैग ओवर (केवल प्रारंभिक ड्रैग पर नहीं) के दौरान घटनाएं प्राप्त करना

यह अच्छी तरह से काम करता है, लेकिन वर्तमान में तर्क एक मेज पर उपयोगकर्ता ड्रैग बूँदें पंक्ति जब नई पंक्ति पंक्ति वे पर गिरा नीचे जोड़ा जाता है कि है।

बेहतर होगा कि नई पंक्ति के ऐड स्थिति पर कि क्या उपयोगकर्ता किसी मौजूदा पंक्ति की ऊपरी या निचली छमाही में गिरा आधारित था होगा।

यह काफी आसान drop स्थिति में गणना करने के लिए है, लेकिन मैं के रूप में उपयोगकर्ता खींच लेता है (जो मैं दो सीएसएस वर्गों droppable-above और droppable-below उदाहरण के लिए के माध्यम से करना होगा) यूआई प्रतिक्रिया देने की जरूरत है।

यह संभव हो सकता है के रूप में over घटना केवल एक बार आग नहीं लगती; जब उपयोगकर्ता प्रारंभ में ड्रॉपपेल तत्व पर ड्रैग करता है।

यह माउस की प्रत्येक गतिविधि के लिए आग को उपयोगकर्ता के एक droppable तत्व खत्म हो गया है over घटना प्राप्त करने के लिए संभव है?

यदि हां, तो मैं यह करने के लिए सक्षम होगा:

$("tr.droppable").droppable({ 
    over: function(event, ui) { 
     if (/* mouse is in top half of row */) { 
      $(this).addClass("droppable-above").removeClass("droppable-below"); 
     } 
     else { 
      $(this).removeClass("droppable-above").addClass("droppable-below"); 
     } 
    }, 

    out: function(event, ui) { 
     $(this).removeClass("droppable-above").removeClass("droppable-below"); 
    }, 

    drop: function(event, ui) { 
     $(this).removeClass("droppable-above").removeClass("droppable-below"); 
     if (/* mouse is in top half of row */) { 
      // Add new row above the dropped row 
     } 
     else { 
      // Add new row below the dropped row 
     } 
    } 
}); 

सीएसएस शैलियों कुछ जैसा होगा ...

droppable-above { border-top: solid 3px Blue; } 
droppable-below { border-bottom: solid 3px Blue; } 
+0

क्या सीमा प्रतिक्रिया के बजाय क्रमबद्ध विकल्प है? यानी जब आप इसे खींचते हैं तो पंक्ति –

+0

@ गैरी डालने के लिए जगह बनाने के लिए दिखाई देगा: सुझाव के लिए धन्यवाद, लेकिन मुझे नहीं लगता कि सॉर्टबेल मेरी मदद करेंगे। मेरी समस्या पंक्तियों को सॉर्ट करने की बजाय नई पंक्तियों को जोड़ने के लिए विशिष्ट है। मेरा यूआई वास्तव में उपयोगकर्ता को जोड़ने के बाद तालिका पंक्तियों को सॉर्ट करने की अनुमति देता है, और यह tableDnD jQuery प्लगइन का उपयोग करके किया जाता है। –

उत्तर

28

जैसा कि आपने कहा था, over (इसके समकक्ष out की तरह) केवल एक बार छोड़ने योग्य पर उठाया जाता है। दूसरी ओर, खींचने योग्य की drag घटना हर बार माउस चालें उठाया, और कार्य हेतु उपयुक्त लग रहा है। बहरहाल, इस रणनीति के साथ दो समस्याओं:

  • drag उठाया है या नहीं, खींचने योग्य वास्तव में एक droppable पर स्थित है,
  • भी उस स्थिति में, droppable ईवेंट हैंडलर तक नहीं पहुंचेगी।

    $("tr.droppable").droppable({ 
        over: function(event, ui) { 
         if (/* mouse is in top half of row */) { 
          $(this).removeClass("droppable-below") 
            .addClass("droppable-above"); 
         } 
         else { 
          $(this).removeClass("droppable-above") 
            .addClass("droppable-below"); 
         } 
         ui.draggable.data("current-droppable", $(this)); // Associate. 
        }, 
    
        out: function(event, ui) { 
         ui.draggable.removeData("current-droppable");  // Break association. 
         $(this).removeClass("droppable-above droppable-below"); 
        }, 
    
        drop: function(event, ui) { 
         ui.draggable.removeData("current-droppable");  // Break association. 
         $(this).removeClass("droppable-above droppable-below"); 
         if (/* mouse is in top half of row */) { 
          // Add new row above the dropped row. 
         } 
         else { 
          // Add new row below the dropped row. 
         } 
        } 
    }); 
    

    अब जब कि: दोनों समस्याओं को हल करने

एक तरह से out और drop संचालकों में, droppable और over हैंडलर में खींचने योग्य संबद्ध करने के लिए jQuery के data() सुविधा का उपयोग कर, और अलग उन्हें है खींचने योग्य droppable इस पर झूठ बोल रही है जानता है, हम एक drag ईवेंट हैंडलर में तत्व की उपस्थिति को अद्यतन कर सकते हैं:

$(".draggable").draggable({ 
    drag: function(event, ui) { 
     var $droppable = $(this).data("current-droppable"); 
     if ($droppable) { 
      if (/* mouse is in top half of row */) { 
       $droppable.removeClass("droppable-below") 
          .addClass("droppable-above"); 
      } else { 
       $droppable.removeClass("droppable-above") 
          .addClass("droppable-below"); 
      } 
     } 
    } 
}); 

जो कोड निम्नानुसार है वह एक साधारण परीक्षण केस है जो इस समाधान को प्रदर्शित करता है (यह मूल रूप से उपरोक्त टिप्पणी किए गए अंतराल को भरता है और सहायक पैटर्न में सामान्य पैटर्न को प्रतिबिंबित करता है)। ड्रॉपपॉबल सेटअप पिछले उदाहरण की तुलना में थोड़ा अधिक जटिल है, मुख्य रूप से क्योंकि नव निर्मित टेबल पंक्तियों को उनके भाई बहनों की तरह छोड़ने योग्य होना चाहिए।

आप परिणाम this fiddle में देख सकते हैं।

HTML:

<div class="draggable">New item 1</div> 
<div class="draggable">New item 2</div> 
<div class="draggable">New item 3</div> 
<div class="draggable">New item 4</div> 
<div class="draggable">New item 5</div> 
<p>Drag the items above into the table below.</p> 
<table> 
    <tr class="droppable"><td>Item 1</td></tr> 
    <tr class="droppable"><td>Item 2</td></tr> 
    <tr class="droppable"><td>Item 3</td></tr> 
    <tr class="droppable"><td>Item 4</td></tr> 
    <tr class="droppable"><td>Item 5</td></tr> 
</table> 

सीएसएस:

p { 
    line-height: 32px; 
} 

table { 
    width: 100%; 
} 

.draggable { 
    background-color: #d0ffff; 
    border: 1px solid black; 
    cursor: pointer; 
    padding: 6px; 
} 

.droppable { 
    background-color: #ffffd0; 
    border: 1px solid black; 
} 

.droppable td { 
    padding: 10px; 
} 

.droppable-above { 
    border-top: 3px solid blue; 
} 

.droppable-below { 
    border-bottom: 3px solid blue; 
} 

जावास्क्रिप्ट:

$(document).ready(function() { 
    $(".draggable").draggable({ 
     helper: "clone", 
     drag: function(event, ui) { 
      var $droppable = $(this).data("current-droppable"); 
      if ($droppable) { 
       updateHighlight(ui, $droppable); 
      } 
     } 
    }); 

    initDroppable($(".droppable")); 

    function initDroppable($elements) 
    { 
     $elements.droppable({ 
      over: function(event, ui) { 
       var $this = $(this); 
       updateHighlight(ui, $this); 
       ui.draggable.data("current-droppable", $this); 
      }, 
      out: function(event, ui) { 
       cleanupHighlight(ui, $(this)); 
      }, 
      drop: function(event, ui) { 
       var $this = $(this); 
       cleanupHighlight(ui, $this); 
       var $new = $this.clone().children("td:first") 
           .html(ui.draggable.html()).end(); 
       if (isInUpperHalf(ui, $this)) { 
        $new.insertBefore(this); 
       } else { 
        $new.insertAfter(this); 
       } 
       initDroppable($new); 
      } 
     }); 
    } 

    function isInUpperHalf(ui, $droppable) 
    { 
     var $draggable = ui.draggable || ui.helper; 
     return (ui.offset.top + $draggable.outerHeight()/2 
       <= $droppable.offset().top + $droppable.outerHeight()/2); 
    } 

    function updateHighlight(ui, $droppable) 
    { 
     if (isInUpperHalf(ui, $droppable)) { 
      $droppable.removeClass("droppable-below") 
         .addClass("droppable-above"); 
     } else { 
      $droppable.removeClass("droppable-above") 
         .addClass("droppable-below"); 
     } 
    } 

    function cleanupHighlight(ui, $droppable) 
    { 
     ui.draggable.removeData("current-droppable"); 
     $droppable.removeClass("droppable-above droppable-below"); 
    } 
}); 
+0

बहुत ज्यादा फ्रेडेरिक हामिदी! समस्या के लिए स्वच्छ और सरल समाधान + अच्छा स्पष्टीकरण और डेमो (jsfiddle), और अधिक नहीं पूछ सका! – loostro

+0

आप महोदय, मेरे नायक हैं। :) –

0

यह एक नहीं बल्कि कच्चे तेल (और codeless) है समाधान, लेकिन आप अपने ड्रॉपपैबल के साथ होवर क्लास विकल्प का उपयोग करके और ड्रॉपपैबल व्यवहार सेट करने के लिए "होवरिंग" नामक एक नई कक्षा बना सकते हैं जो केवल तभी होता है जब ड्रैगगेबल ड्रॉपपेल पर होवर हो रहा हो। यह "होवरिंग" कक्षा तब (यह कच्ची बिट है) कुछ प्रकार के अंतहीन पाश या किसी अन्य प्रकार के चेकर चला सकती है; मैंने पहले इन कक्षाओं का उपयोग नहीं किया है, इसलिए मैं इस बिंदु से पहले किसी और विनिर्देश के बारे में नहीं सोच सकता। =/

संपादित करें: यहां तक ​​कि cruder, आप वैकल्पिक अक्षम और droppable "मँडरा" वर्ग का उपयोग कर सक्रिय करने के सकता है, मैं निश्चित रूप से हालांकि यह समकालिक रूप से करता हूं, और साथ ही साथ उदार समय के साथ चित्रण भी करता हूं। बारी को निष्क्रिय और कॉल चाहिए ट्रिगर घटनाओं में से एक है, हालांकि आप किस पता लगाने के लिए के साथ प्रयोग करना होगा सक्षम करें।

2

मैं एक ही मुद्दा मार रहा हूँ और हो गए हैं मैं उन दो समाधानों के बारे में सोच रहा हूं जो वे साझा करेंगे यदि वे दूसरों को निर्देश देते हैं जो अपेक्षाकृत दुर्लभ आवश्यकता पाते हैं।

  • दो div समाधान: पंक्ति, स्टैक हो जाते हैं तैनात की प्रत्येक कोशिका और z- सूचकांक यूआई हस्तक्षेप से बचाने के लिए -1 पर सेट के साथ प्रत्येक 50% अधिक है और पूरी चौड़ाई में दो divs जोड़ें। अब इन ड्रॉपपैबल्स को बनाएं और पैरेंट सेल या पंक्ति के वर्गों को टॉगल करने के लिए 'ओवर' और 'आउट' ईवेंट का उपयोग करें।

  • छोड़ने योग्य और अपने स्वयं के टकराव की पहचान रोल करें: ड्रॉप करने योग्य प्रभाव की नकल करने के लिए अपना स्वयं का टक्कर पहचान लिखें। यह अधिक स्वतंत्रता प्रदान करेगा लेकिन कुछ गंभीर कोडिंग का कारण होगा और इसलिए आकस्मिक आवश्यकता के लिए नहीं है। प्रदर्शन के मुद्दों के लिए भी अतिसंवेदनशील होगा। उस ने कहा, कुछ स्पष्ट केस-आधारित शॉर्टकट होना चाहिए जो आपके पक्ष में काम करेंगे।

मुझे कम कोड समाधान के किसी अन्य दृष्टिकोण को सुनने में दिलचस्पी होगी।

1

मैंने अभी इस समस्या को मारा है। यदि आप केवल 'ड्रैग' ईवेंट में हिट परीक्षण लागू करते हैं तो बहुत कुछ आवश्यक नहीं है। यहां मैंने अपने सभी ड्रॉप लक्ष्यों को .myDropTarget के साथ टैग किया है, इसलिए उन सभी को ढूंढना आसान है, उनके माध्यम से लूप करें और जांचें कि माउस उनके ऊपर है या नहीं।

कुछ इस तरह:

thingToBeDragged.draggable({ 
    drag: function(evt) { 

     $('.myDropTarget').removeClass('topHalf bottomHalf').each(function() { 
      var target = $(this), o = target.offset(), 
       x = evt.pageX - o.left, y = evt.pageY - o.top; 

      if (x > 0 && y > 0 && x < target.width() && y < target.height()) { 

       // mouse is over this drop target, but now you can get more 
       // particular: is it in the top half, bottom half, etc. 

       if (y > target.height() * 0.5) { 
        target.addClass('topHalf'); 
       } else { 
        target.addClass('bottomHalf'); 
       } 
      } 
     }); 
    }, 
    stop: function() { 
     var droppedOn = $('.topHalf, .bottomHalf'); 
    } 
}); 
1

एक अन्य विधि संकेत तत्व को कक्षा या अन्य निर्वाचक जोड़ना है।फिर ड्रैग करने योग्य परिभाषा में, ड्रैग हैंडलर पर, संकेत स्थिति अपडेट करें:

$('#dropArea').droppable({ 
     over: function(event, ui) 
      // Create a clone 50 pixels above and 100 to the left of drop area 
      $('#someHint').clone() 
        .css({ 
         position: 'absolute', 
         top: ui.offset.top+50, 
         left: ui.offset.left-50 
        }) 
        .addClass("clone")   // Mark this as a clone, for hiding on drop or out 
        .addClass("dragHelper")  // Mark this as a hint, for moving with drag 
        .appendTo(document.body) 


     }, 
     out: function(event, ui) { 
      $('.clone').remove();      // Remove any hints showing 
     }, 
     drop: function(event, ui) { 
      $('.clone').remove();      // Remove any hints showing 
     } 
    }); 

$("#mydiv").draggable({ 
     drag: function(event, ui) { 
      $('.dragHelper').css('left',ui.offset.left); 
      $('.dragHelper').css('top',ui.offset.top); 
     } 

}); 
संबंधित मुद्दे