2013-01-07 25 views
6

Tôi đang cố gắng để theo dõi một DragEnter/rời cho toàn bộ màn hình, được cho đến nay làm việc tốt trong Chrome/Safari, lịch sự của các plugin draghover từ https://stackoverflow.com/a/10310815/698289 như trong:Firefox bắn dragleave khi kéo qua văn bản

$.fn.draghover = function(options) { 
    return this.each(function() { 

     var collection = $(), 
      self = $(this); 

     self.on('dragenter', function(e) { 
      if (collection.size() === 0) { 
       self.trigger('draghoverstart'); 
      } 
      collection = collection.add(e.target); 
     }); 

     self.on('dragleave drop', function(e) { 
      // timeout is needed because Firefox 3.6 fires the dragleave event on 
      // the previous element before firing dragenter on the next one 
      setTimeout(function() { 
       collection = collection.not(e.target); 
       if (collection.size() === 0) { 
        self.trigger('draghoverend'); 
       } 
      }, 1); 
     }); 
    }); 
}; 

function setText(text) { 
    $('p.target').text(text); 
} 

$(document).ready(function() { 
    $(window).draghover().on({ 
     'draghoverstart': function() { 
      setText('enter'); 
     }, 
     'draghoverend': function() { 
      setText('leave'); 
     } 
    }); 
}); 

Tuy nhiên Firefox vẫn đem lại cho tôi những vấn đề khi tôi kéo qua mục văn bản, đây là một fiddle để chứng minh: http://jsfiddle.net/tusRy/6/

đây có phải là một lỗi Firefox hoặc này có thể được thuần hóa với JS? Hoặc là có một phương pháp mạnh mẽ hơn để thực hiện tất cả điều này?

Cảm ơn!

CẬP NHẬT: Cập nhật fiddle thành http://jsfiddle.net/tusRy/6/ để giảm sự lộn xộn một chút. Để giải thích hành vi mong đợi của fiddle:

  • Kéo tệp vào cửa sổ và mục tiêu p.target phải là "ENTER" màu vàng.
  • Kéo tệp ra khỏi cửa sổ và p.target phải là "LEAVE" màu đỏ.
  • Thả tệp trong cửa sổ và p.target phải là "LEAVE" màu đỏ.

Trong firefox, sự kiện LEAVE được kích hoạt khi bạn kéo tệp qua văn bản.

+0

Tôi đã làm việc xung quanh điều này bây giờ bằng cách sử dụng một div lớp phủ, theo http://jsfiddle.net/tusRy/7/ tuy nhiên tôi không thực sự hạnh phúc về việc này là giải pháp vì vậy tôi sẽ để lại câu hỏi này mở cho đến khi có ý tưởng tốt hơn. – DanH

Trả lời

1

Tôi đã đưa ra một giải pháp nhưng chưa thử nghiệm trên các trình duyệt khác ngoài Chrome và FF nhưng vẫn đang hoạt động cho đến nay. Đây là cách setTimeout trông bây giờ:

setTimeout(function() { 
    var isChild = false; 

    // in order to get permission errors, use the try-catch 
    // to check if the relatedTarget is a child of the body 
    try { 
     isChild = $('body').find(e.relatedTarget).length ? true : isChild; 
    } 
    catch(err){} // do nothing 

    collection = collection.not(e.target); 
    if (collection.size() === 0 && !isChild) { 
     self.trigger('draghoverend'); 
    } 
}, 1); 

Toàn bộ mã ở đây - http://jsfiddle.net/tusRy/13/.

Ý tưởng là kiểm tra xem thẻ có liên quan là con của cơ thể hay không, trong trường hợp đó chúng tôi vẫn đang ở trong Trình duyệt và sự kiện draghoverend sẽ không được kích hoạt. Vì điều này có thể ném lỗi khi di chuyển ra khỏi cửa sổ, tôi đã sử dụng một phương pháp thử để tránh nó.

Vâng, có lẽ ai đó có nhiều kỹ năng hơn về JS có thể cải thiện điều này :)

8

Kể từ phiên bản 22.0 Firefox vẫn đang thực hiện việc này. Khi bạn kéo qua một nút văn bản, nó sẽ kích hoạt hai loại sự kiện dragenterdragleave: một trong đó mục tiêu sự kiện và relatedTarget là BOTH phần tử mẹ của nút văn bản và phần tử khác nơi đích là phần tử cha và relatedTarget là văn bản thực nút (thậm chí không phải là một phần tử DOM thích hợp).

Cách giải quyết chỉ là để kiểm tra hai loại sự kiện trong dragenterdragleave bạn xử lý và bỏ qua chúng:

try { 
    if(event.relatedTarget.nodeType == 3) return; 
} catch(err) {} 
if(event.target === event.relatedTarget) return; 

tôi sử dụng một khối try/catch để kiểm tra nodeType vì thỉnh thoảng các sự kiện cháy (inexplicably) từ bên ngoài tài liệu (ví dụ: trong iframe khác) và cố gắng truy cập nodeType của họ sẽ ném lỗi quyền.

Đây là việc thực hiện: http://jsfiddle.net/9A7te/

+1

Tôi tin rằng có một vấn đề với xử lý sự kiện của jQuery-2.1.1 cho dragenter và dragleave: Tôi đã nhận thấy rằng thay vì báo cáo nút văn bản vi phạm như event.target trên dragenter và dragleave, nó sẽ chuyển phần tử cha của nút văn bản . Nếu bạn vẫn còn nhận thấy vấn đề tôi tự hỏi nếu đi bản địa ở đây có thể giúp đỡ. – Gavin

+1

bằng cách câu trả lời này đã giúp tôi nhiều nhất. Và trong trường hợp câu trả lời của tôi ở trên không rõ ràng: tôi có nghĩa là trong lỗi này, chính jQuery sẽ không chính xác sao chép các mục tiêu sự kiện vào đối tượng Sự kiện tùy chỉnh của nó. Tôi đã triển khai kiểm tra nodeType dựa trên event.originalEvent.target và event.originalEvent.relatedTarget với kết quả tốt – Gavin

+1

Hoạt động hoàn hảo! Tôi đã thêm nó vào chính plugin đó để tránh phải viết lại nó trong trình xử lý sự kiện kết thúc. Hoạt động hoàn toàn tốt trong Chrome và Firefox. Đã không được thử nghiệm trong các trình duyệt khác để xác minh bất kỳ lỗi goofy nào, nhưng đây là hai trình duyệt chính mà tôi phải hỗ trợ thông thường. – Demonslay335

1

1) vùng thả của bạn nên chỉ có một phần tử con, mà có thể có tất cả mọi thứ khác mà bạn cần.Một cái gì đó như

<div id="#dropzone"> 
    <div><!--Your contents here--></div> 
</div> 

2) Sử dụng CSS này:

#dropzone * { pointer-events: none; } 

Bạn có thể cần phải bao gồm các :before:after kể từ khi * không áp dụng đối với họ.

Điều này là đủ để cho phép thả hoạt động trong Firefox và Chrome. Trong ví dụ của bạn, sẽ đủ để thêm:

body * { pointer-events: none; } 

Ở cuối CSS. Tôi đã thực hiện nó ở đây:

ví dụ khác:

1

Tôi tìm thấy câu trả lời trong một câu trả lời không được lựa chọn cho câu hỏi SO này hỏi về dragleave firing on child elements. Tôi có một số <div> có nhiều phần tử con. Lớp phủ bán mờ đục <span> sẽ hiển thị trên <div> bất cứ khi nào có dragenter trên trang. Như bạn thấy, 'di chuyển' không giống như mouseover. Nó kích hoạt dragleave bất cứ khi nào bạn di chuột qua phần tử con.

Giải pháp? Dragout Nó làm cho dragover hoạt động giống như mouseover. Rất ngắn.

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