2012-08-23 19 views
6

Tôi đã điều sau đây:Chỉ thả cho phần tử đó được xem

Tôi cố gắng để thiết lập nó để khi bạn kéo mặt hàng đó, nó chỉ được giảm xuống phần tử div mà bạn có thể nhìn thấy, và là không phải được che đậy.

Vì vậy, tôi đã sử dụng này JS:

$(".draggable").draggable({ 
    helper: "clone" 
}) 
$("#bottom, .draggable").droppable({ 
    drop: function(event, ui) { 
     var $this = $(this), 
      $dragged = $(ui.draggable); 
     $this.append($dragged.clone()); 
    }, 
    hoverClass: "dragHover" 
})​ 

Nhưng nó giảm các yếu tố trong cả nơi mặc dù chỉ là một trong những vùng thả là không có thể nhìn thấy!

Làm cách nào để khắc phục sự cố để điều này xảy ra không phải xảy ra?

Fiddle: http://jsfiddle.net/maniator/Wp4LU/


tắm Info để tái trang mà không fiddle:

HTML:

<div id="top"> 
    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 
    </div> 

    <div id="bottom"></div> 

CSS:

.draggable { 
    border: 1px solid green; 
    background: white; 
    padding: 5px; 
} 

.dragHover{ 
    background: blue; 
} 

#top { 
    height: 500px; 
    overflow-y: scroll; 
} 
#bottom { 
    height: 150px; 
    overflow-y: scroll; 
    border: red solid 4px; 
} 

+0

Vì nó không giải quyết được sự cố trong máy chủ trực tiếp, đây là [fiddle] (http://jsfiddle.net/ult_combo/Wp4LU/18/) bằng thuộc tính bị vô hiệu hóa để bắt chước 'event.stopImmediatePropagation' thành các tiện ích giao diện người dùng khác, hy vọng nó có thể được cải thiện nếu không tìm thấy cách nào tốt hơn. –

+0

@Neal Đừng nghĩ rằng chúng tôi có thể sử dụng một số jquery propert như $ this.is (": visible"). Tôi không biết nhiều về jquery nhưng bạn có thể nói rằng đây là một nỗ lực của một novice – Moons

Trả lời

2

Thử thiết lập với chức năng accept. The working demo.

$("#bottom, .draggable").droppable({ 
    drop: function(event, ui) { 
     var $this = $(this), 
      $dragged = $(ui.draggable); 
     $this.append($dragged.clone()); 
    }, 
    accept: function() { 
     var $this = $(this), divTop= $("#top"); 
     if ($this.is(".draggable")) { 
      return $this.offset().top < divTop.offset().top + divTop.height() ; 
     } 
     return true; 
    }, 
    hoverClass: "dragHover" 
})​;​ 
+0

Holy awesomeness^_^điều này có vẻ là làm việc :-). Tôi phải kiểm tra nó nhiều hơn một chút :-D. Cảm ơn bạn rất nhiều! – Neal

2

Nếu tôi có bạn ngay - một trong những điều này nên giải quyết vấn đề của bạn - http://jsfiddle.net/Wp4LU/60/ Ngoài ra bạn có thể viết tùy chỉnh chức năng chấp nhận - http://jqueryui.com/demos/droppable/#option-accept

Code:

var draggableList = $('#top'); 

$(".draggable").draggable({ 
    helper: "clone" 
}); 
$("#bottom, .draggable").droppable({ 
    drop: function(event, ui) { 
     var $this = $(this), 
      $dragged = $(ui.draggable); 

     if ($this.hasClass("draggable")) { 
      if ($this.position().top >= draggableList.height() || 
       $this.position().top + $this.outerHeight() >= 
       draggableList.height()) 
       return; 
     } 

     $this.append($dragged.clone()); 
    }, 
    hoverClass: "dragHover" 
})​;​ 
+0

Điều này làm việc độc đáo trong fiddle ... nhưng nó dường như không được làm việc trong mã thực sự của tôi (có vẻ hơi khác nhau) .... – Neal

0

Theo nguồn (jquery.ui.droppable.js), thao tác thả sẽ tìm kiếm tất cả các phân đoạn đủ điều kiện và áp dụng chức năng thả cho mỗi giao điểm với nó:

drop: function(draggable, event) { 

    var dropped = false; 
    $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { 

     if(!this.options) return; 
     if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) 
      dropped = this._drop.call(this, event) || dropped; 

(Phiên bản cũ có điều kiện "OR" cuối cùng được đảo ngược, vì vậy nó sẽ chỉ áp dụng cho một lần có thể phân tách. Hãy thử fiddle của bạn bằng cách sử dụng jQuery 1.5.2/jQuery UI 1.8.9, và thấy rằng nó chỉ giảm xuống một phần tử, mặc dù là "sai" ...)

Và mọi chế độ khoan dung hiện chỉ được thực hiện trong chức năng $.ui.intersect có tính đến các tọa độ (x, y):

switch (toleranceMode) { 
    case 'fit': 
     return (l <= x1 && x2 <= r 
      && t <= y1 && y2 <= b); 
     break; 
    case 'intersect': 
     return (l < x1 + (draggable.helperProportions.width/2) // Right Half 
      && x2 - (draggable.helperProportions.width/2) < r // Left Half 
      && t < y1 + (draggable.helperProportions.height/2) // Bottom Half 
      && y2 - (draggable.helperProportions.height/2) < b); // Top Half 
     break; 
    ... 

Vì vậy, trừ khi ai đó thêm chế độ khoan dung nhận biết z-index, lựa chọn duy nhất của bạn là giải quyết vấn đề bằng cách nào đó. Tôi muốn đề nghị đầu tiên thêm mỗi ứng cử viên droppable đến một tập và, khi đó là thời gian để thả, chỉ chọn một trong đó là "gần nhất" vào màn hình:

$("#bottom, .draggable").droppable({ 
    over: function(event, ui) { 
     if (!ui.draggable.data("drop-candidates")) 
      ui.draggable.data("drop-candidates",[]); 
     ui.draggable.data("drop-candidates").push(this); 
    }, 
    out: function(event, ui) { 
     var that = this, 
      candidates = ui.draggable.data("drop-candidates") || []; 
     ui.draggable.data("drop-candidates", $.grep(candidates, function(e) { 
      return e != that; 
     }); 
    }, 
    drop: function(event, ui) { 
     var $this = $(this), 
      $dragged = $(ui.draggable); 
     var candidates = $.data("drop-candidates").sort(closestToScreen); 
     if (candidates[0] == this) 
      $this.append($dragged.clone()); 
    }, 
    hoverClass: "dragHover" 
})​ 

Bây giờ, thực hiện so sánh closestToScreen là phần khó khăn . W3C CSS Specification mô tả cách các công cụ kết xuất nên sắp xếp các yếu tố để vẽ, nhưng tôi đã không thể tìm thấy cho đến nay một cách dễ dàng để truy cập thông tin này. Tôi cũng asked this question ở đây tại SO, có thể ai đó sẽ tìm thấy một cách tốt.


P.S. Nếu sửa đổi mã nguồn jQuery UI một lựa chọn, bạn có thể thử thực hiện một z-index chế độ khoan dung ý thức sử dụng document.getElementFromPoint, như this answer để nói câu hỏi gợi ý:

var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, 
    y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; 
switch (toleranceMode) { 
    ... 
    case 'z-index-aware': 
     return document.elementFromPoint(x1,y1) == droppable; 
     break; 

(mà sẽ đảm bảo chỉ yếu tố quyền bên dưới góc trên bên trái của draggable sẽ được coi là "đủ tốt" như một mục tiêu thả - không lý tưởng, nhưng tốt hơn so với những gì chúng ta có cho đến nay, một giải pháp tương tự có thể được điều chỉnh để sử dụng tọa độ con trỏ chuột)

Và, không, bạn không thể sử dụng phương pháp này với cách giải quyết được trình bày trước đây: tại thời điểm thả xảy ra, trình trợ giúp kéo kéo là phần tử gần màn hình nhất ... (Chỉnh sửa: d'oh! Nó sẽ không hoạt động nếu được thực hiện như một chế độ khoan dung, hoặc vì cùng một lý do ...)

0

Nếu bạn chỉ muốn thả vào yếu tố bạn có thể thấy bạn có thể thay đổi chọn của bạn:

$(".draggable:visible").draggable({ 
    helper: "clone" 
}); 
$("#bottom, .draggable:visible").droppable({ 
    drop: function(event, ui) { 
     var $this = $(this), 
      $dragged = $(ui.draggable); 
     $this.append($dragged.clone()); 
    }, 
    hoverClass: "dragHover" 
})​; 

Hoặc khi bạn ẩn một yếu tố thay đổi lớp kéo của mình bằng một cái gì đó khác.

+0

Thao tác này sẽ không hoạt động ... sự kiện ** không được ủy quyền .... – Neal

+0

@Neal có vẻ như tôi đã không gặp vấn đề thực sự ở đây. có vẻ như bạn đã nhận được câu trả lời từ một bài đăng khác. chúc may mắn – TecHunter

Các vấn đề liên quan