2011-11-08 18 views
27

Chúng tôi đang làm việc trên một công cụ JavaScript có mã cũ hơn trong đó, vì vậy chúng tôi không thể viết lại toàn bộ công cụ.Làm cách nào để xử lý một nhấp chuột ở bất kỳ đâu trong trang, ngay cả khi một phần tử nhất định dừng quá trình truyền?

Bây giờ, một menu đã được thêm vào vị trí cố định ở phía dưới và khách hàng rất thích nó để có nút bật/tắt để mở và đóng menu, ngoại trừ việc đóng cần phải tự động xảy ra khi người dùng bắt đầu thực hiện mọi thứ của trình đơn, ví dụ: khi người dùng quay trở lại trang và chọn thứ gì đó hoặc nhấp vào trường biểu mẫu.

Điều này có thể về mặt kỹ thuật làm việc với một sự kiện click trên body, gây ra trên bất kỳ nhấp chuột, tuy nhiên có rất nhiều mặt hàng trong các mã cũ, nơi mà một sự kiện nhấp chuột đã được xử lý vào một liên kết nội bộ, và return false đã được thêm vào nhấp chuột , để trang web không tiếp tục với thẻ href của liên kết.

Vì vậy, rõ ràng, một chức năng chung như thế này không hoạt động, nhưng không phải khi được nhấp vào một liên kết nội bộ trong đó trả về false dừng quá trình truyền.

$('body').click(function(){ 
    console.log('clicked'); 
}); 

Có cách nào tôi có thể buộc các sự kiện cơ thể nhấp chuột anyway, hoặc là có một cách khác để tôi có thể để cho biến mất menu, sử dụng một số sự kiện click toàn cầu hay bất cứ điều gì tương tự?

Không cần phải viết lại tất cả các nhấp chuột khác trong ứng dụng đã được tạo năm trước. Đó sẽ là một nhiệm vụ quái vật, đặc biệt là kể từ khi tôi không có đầu mối làm thế nào tôi sẽ viết lại chúng, mà không có sự trở lại sai, nhưng vẫn không để cho họ đi đến href của họ.

Trả lời

44

Sự kiện trong triển khai DOM hiện đại có hai giai đoạn, chụpbubbling.Giai đoạn bắt giữ là pha đầu tiên, chảy từ defaultView của tài liệu đến mục tiêu sự kiện, tiếp theo là pha bọt, chảy từ mục tiêu sự kiện trở về defaultView. Để biết thêm thông tin, hãy xem http://www.w3.org/TR/DOM-Level-3-Events/#event-flow.

Để xử lý các giai đoạn chụp của một sự kiện, bạn cần phải thiết lập các tham số thứ ba cho addEventListener để true:

document.body.addEventListener('click', fn, true); 

Đáng buồn thay, như Wesley đã đề cập, giai đoạn chụp của một sự kiện không thể được xử lý đáng tin cậy, hoặc ở tất cả, trong các trình duyệt cũ hơn.

Một giải pháp khả thi là để xử lý các sự kiện mouseup thay vào đó, kể từ khi sự kiện đặt hàng cho các nhấp chuột là:

  1. mousedown
  2. mouseup
  3. nhấp chuột

Nếu bạn có thể chắc chắn rằng bạn có không có trình xử lý nào hủy sự kiện mouseup, thì đây là một cách (và, được cho là một cách tốt hơn) để đi. Một điều cần lưu ý là nhiều, nếu không nhất (nếu không phải tất cả), menu UI biến mất trên chuột xuống.

+2

Đối với bất cứ ai tự hỏi nếu họ có thể sử dụng này, đây là trang caniuse: http://caniuse.com/#feat=addeventlistener câu trả lời ngắn là có, miễn là bạn không quan tâm về IE8 –

0

Tôi nghĩ rằng đây là những gì bạn cần:

$("body").trigger("click"); 

này sẽ cho phép bạn kích hoạt các sự kiện cơ thể nhấp chuột từ bất cứ nơi nào.

+0

sẽ kích hoạt nếu một cái gì đó lồng sâu hơn trong dom ngăn chặn sự kiện tuyên truyền mặc dù? – Matt

+0

Tôi nghĩ rằng vấn đề là các sự kiện nhấp chuột đang được nuốt bằng cách trả về false từ các trình xử lý sự kiện trên các liên kết nhất định, không phải là sự kiện nhấp chuột không thể được tạo ra ở nơi đầu tiên. –

0

Nếu bạn chắc chắn rằng đây là đầu tiên sự kiện công việc xử lý, một cái gì đó như thế này có thể làm lừa:

$('*').click(function(event) { 
    if (this === event.target) { // only fire this handler on the original element 
     alert('clicked'); 
    } 
}); 

Lưu ý rằng, nếu bạn có nhiều thành phần trong trang, điều này sẽ rất chậm và sẽ không hoạt động đối với bất kỳ thứ gì được thêm động.

+0

điều năng động có thể dễ dàng được sửa qua $ ("*"). Trên ("click", function() {}); nhưng bất kể đây là một ý tưởng tồi. – Bbit

6

Hợp tác với Andy E, đây là mặt tối của lực lượng:

var _old = jQuery.Event.prototype.stopPropagation; 

jQuery.Event.prototype.stopPropagation = function() { 
    this.target.nodeName !== 'SPAN' && _old.apply(this, arguments); 
};  

Ví dụ: http://jsfiddle.net/M4teA/2/

Hãy nhớ rằng, nếu tất cả các sự kiện này được ràng buộc qua jQuery, bạn có thể xử lý những trường hợp đó ngay tại đây. Trong ví dụ này, chúng tôi chỉ gọi số .stopPropagation() gốc nếu chúng tôi không xử lý một số <span>.


Bạn không thể ngăn chặn việc ngăn chặn, không.

Điều bạn có thể làm là viết lại các trình xử lý sự kiện đó theo cách thủ công trong mã. Đây là một doanh nghiệp phức tạp, nhưng nếu bạn biết cách truy cập các phương thức xử lý được lưu trữ, bạn có thể làm việc xung quanh nó. Tôi chơi xung quanh với nó một chút, và đây là kết quả của tôi:

$(document.body).click(function() { 
    alert('Hi I am bound to the body!'); 
}); 

$('#bar').click(function(e) { 
    alert('I am the span and I do prevent propagation'); 
    e.stopPropagation(); 
}); 

$('#yay').click(function() { 
    $('span').each(function(i, elem) { 
     var events  = jQuery._data(elem).events, 
      oldHandler = [ ], 
      $elem   = $(elem); 

     if('click' in events) {       
      [].forEach.call(events.click, function(click) { 
       oldHandler.push(click.handler); 
      }); 

      $elem.off('click'); 
     } 

     if(oldHandler.length) { 
      oldHandler.forEach(function(handler) { 
       $elem.bind('click', (function(h) { 
        return function() { 
         h.apply(this, [{stopPropagation: $.noop}]); 
        }; 
       }(handler))); 
      }); 
     } 
    }); 

    this.disabled = 1; 
    return false; 
}); 

Ví dụ: http://jsfiddle.net/M4teA/

Chú ý, các mã trên sẽ chỉ làm việc với jQuery 1.7. Nếu những sự kiện nhấp chuột đó bị ràng buộc với phiên bản jQuery cũ hơn hoặc "nội dòng", bạn vẫn có thể sử dụng mã nhưng bạn sẽ cần phải truy cập "trình xử lý cũ" khác nhau.

Tôi biết tôi đang giả định rất nhiều điều "kịch bản thế giới hoàn hảo" ở đây, ví dụ, các xử lý đó gọi rõ ràng .stopPropagation() thay vì trả lại false. Vì vậy, nó vẫn có thể là một ví dụ học tập vô dụng, nhưng tôi cảm thấy để đi ra với nó :-)

: hey, return false; sẽ hoạt động tốt, các đối tượng sự kiện được truy cập theo cùng một cách.

+0

Điều này là thông minh. :) –

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