2011-01-04 39 views
9

Sử dụng jQuery, tôi muốn, mà không thay đổi thuộc tính disabled của một nút nhất định, vô hiệu hóa tất cả các sự kiện nhấp chuột cho nó.Làm cách nào để tạm thời vô hiệu hóa các sự kiện nhấp chuột trên một nút mà không thực sự vô hiệu hóa nó?

Tôi đã nghĩ đến việc truy xuất trình xử lý sự kiện nhấp chuột, hủy liên kết chúng và lưu trữ chúng (ví dụ: sử dụng data()).

Sau đó, tôi có thể liên kết lại chúng khi nút được bật lại.

+3

Bạn có thể muốn xem xét lại cách tiếp cận của bạn - nếu bạn muốn có một nút không hoạt động , vô hiệu hóa nó. Những lá cờ đó cho người dùng rõ ràng rằng nút bị tắt. Nó dễ hiểu hơn, đơn giản hơn và phù hợp hơn so với làm việc xung quanh hành vi mặc định. Tại sao bạn muốn tránh vô hiệu hóa nút? –

+0

Vì, AFAIK, các nút bị tắt không thể được tạo kiểu. – Ovesh

Trả lời

16

Không khó để làm từ jQuery đã lưu trữ tất cả các trình xử lý sự kiện của nó là data() trên chính phần tử đó. Bạn có thể nhận (và sửa đổi) đối tượng này thông qua .data().events.

Hãy thử$("#portalLink a").data().events.click = nulltrong giao diện điều khiển của bạn ngay bây giờ để tắt tùy chọn "StackExchange" thả xuống phía trên bên trái của trang này.

Bây giờ bạn có thể dễ dàng lưu một tham chiếu đến bộ xử lý với:

events._click = events.click; 
events.click = null; 

Và sau đó khôi phục chúng bằng cách sử dụng:

events.click = events._click; 
events._click = null; 

Lưu ý rằng điều này sẽ không vô hiệu hóa những sự kiện đang bị ràng buộc qua .delegate() hoặc .live(), khi chúng hoạt động bằng sự kiện sủi bọt/tuyên truyền. Để vô hiệu hóa những người là tốt, chỉ cần gắn một handler mới mà khối tuyên truyền đến các yếu tố tổ tiên:

events._click = events.click; 
events.click = null; 
// Block .live() and .delegate() 
$("#el").click(function (e) { 
    e.stopPropagation(); 
}); 

Bạn thậm chí không cần phải unbind chức năng chặn này khi đó là thời gian để cho phép xử lý một lần nữa, vì events.click = events._click sẽ ghi đè lên chức năng bạn chỉ bị ràng buộc với tất cả các trình xử lý cũ.

+1

Cách tiếp cận này có thể là vấn đề. Đối với một, tôi nghĩ rằng tôi đọc ở đâu đó rằng hành vi này không được hỗ trợ trong các phiên bản mới của jQuery. Nhưng ngay cả khi đó không phải là sự thật, nó không phải là một hành vi tài liệu, vì vậy tôi không thể dựa vào nó cho các phiên bản tương lai của jQuery. – Ovesh

+1

@Ovesh, Ngoài ra, tôi nghĩ Javascript là một trong những ngôn ngữ, có thể do tính chất động, thực tế "nguồn mở" (không bao giờ được biên soạn, đôi khi được rút gọn) và lịch sử không tương thích của trình duyệt, ở đó ít quan tâm đến việc ẩn/bảo vệ chi tiết triển khai. Miễn là những rủi ro được hiểu, và không có sự thay thế tốt hơn tồn tại, sau đó cảm thấy tự do để nhảy vào, sửa đổi nguyên mẫu, chức năng ghi đè, và nói chung .. hack đi;) –

+0

Đồng ý. Tôi sẽ chấp nhận câu trả lời, vì có lẽ không có giải pháp nào tốt hơn. – Ovesh

0

Đó là cách để thực hiện. Nếu bạn đã onclick quy định như một thuộc tính bạn có thể chuyển đổi các thuộc tính busing

$(button_element).attr('click', ''); 

$(button_element).attr('click', 'do_the_regular_action()'); 
+0

Giả sử rằng tôi không biết tất cả các trình xử lý sự kiện được gán cho phần tử. Và có thể có nhiều hơn một. – Ovesh

+0

trong trường hợp đó cách tiếp cận của tôi sẽ không hoạt động – Thariama

0

Bạn có thể sử dụng unbindbind

$('#control').unbind('click');

$('#control').bind('click', NameOfFunctionToCall);

+0

Tôi không nghĩ rằng điều này trả lời câu hỏi của OP (mặc dù tôi có thể sai). Từ âm thanh của nó, có thể có nhiều trình xử lý nhấp chuột và anh ta có thể không có được tham chiếu đến trình xử lý để ràng buộc (ví dụ: chức năng ẩn danh hoặc chức năng trong phạm vi khác). –

+0

Đúng vậy. Xem bình luận của tôi để @Thariama. – Ovesh

3

đây vẫn chưa một cách khác:

$("#myButton").click(function() { 
    if ($(this).attr("temp_disable") == "disabled") { 
     //nothing to do, temporarily disabled... 
    } 
    else { 
     alert("You clicked me!"); 
    } 
}); 

Để "vô hiệu hóa" nó trong 10 giây:

$("#myButton").attr("temp_disable", "disabled"); 
window.setTimeout(function() { $("#myButton").attr("temp_disable", ""); }, 10000); 

test Live: http://jsfiddle.net/yahavbr/ByM6h/

+0

Đó là những gì tôi đã làm. Nhưng vấn đề là, nó phải được thêm vào mọi trình xử lý được xác định. Từ quan điểm thiết kế, đây không phải là giải pháp tốt, bởi vì một số sự kiện có thể được thêm vào bởi mã không nằm trong tầm kiểm soát của tôi. – Ovesh

+1

@Ovesh cách duy nhất để làm điều đó "trên toàn cầu" ngoài việc vô hiệu hóa nút này là thay đổi nó thành một thứ khác, ví dụ: 'div' chỉ trông giống như một nút sau đó thay đổi nó trở lại nút khi hết thời gian - hy vọng các trình xử lý sự kiện sẽ được giữ nguyên, cần kiểm tra nó trước. –

+0

Đó thực sự là một ý tưởng khá hay. Bạn có thể thay thế nó bằng một nút được kích hoạt theo kiểu (không có sự kiện nhấp được đính kèm) và giữ nút gốc bằng cách sử dụng 'dữ liệu()'. Sau đó, thay thế nút gốc trở lại. – Ovesh

0

tôi sẽ mở rộng về câu trả lời (s) được cung cấp bởi Barry và Thariama ... mà tôi nghĩ sẽ làm hài lòng đối Ovesh của:

Bạn có thể thêm một không gian tên cho sự kiện của bạn ràng buộc.Điều đó cho phép bạn tham khảo sự kiện cụ thể đó ràng buộc sau, mà không va chạm với các ràng buộc khác. Tôi nghĩ rằng điều này là sạch hơn so với câu trả lời được chấp nhận ... (Để công bằng, điều này có thể không có sẵn trong jQuery tại thời điểm câu hỏi ban đầu).

// A generic click handler: 
$('.myButton').click(function() { ... }); 

// A namespaced click handler: 
$('.myButton').bind('click.someSituation', function() { ... }); 

// Later you can unbind only the handler you want by using the namespace: 
$('.myButton').unbind('click.someSituation'); 

// The default click handler still works. 
+0

Tôi đoán tôi nên làm cho nó rõ ràng hơn trong câu hỏi. Có thể có nhiều sự kiện nhấp chuột, không phải tất cả các sự kiện đều bị ràng buộc bởi mã của tôi. Giải pháp này không phải là đủ chung chung. – Ovesh

+0

Trong ví dụ của tôi, tệp .click() chung là sự kiện bị ràng buộc bởi một số mã khác. Các .pind không gian tên (click ...) nằm trong mã của bạn. Bạn có thể hủy liên kết trình xử lý nhấp chuột được đặt tên theo vị trí của mình mà không ảnh hưởng đến các trình xử lý nhấp chuột khác. –

+0

Ah, nhưng câu hỏi nói rằng, tôi muốn vô hiệu hóa * tất cả * bấm các sự kiện trên đó. – Ovesh

0

Thay vì thực hiện việc này Sử dụng Javascript chính để thực hiện tác vụ này ví dụ: Hãy xem ví dụ sau.

function MakeSaveDisabled(flg) { 
    if (flg != null) { 
     $(".btnpost").each(function() { 
      this.removeAttribute("disabled"); 
      if (this.hasAttribute("oclickevt")) { 
       this.setAttribute("onclick", this.getAttribute("oclickevt")); 
      } 
     }); 
    } 
    else { 
     $(".btnpost").each(function() { 
      this.setAttribute("disabled", "true"); 
      if (this.getAttribute("onclick") != null) { 
       this.setAttribute("oclickevt", this.getAttribute("onclick")); 
      } 
      this.removeAttribute("onclick"); 
     }); 
    } 
} 

Lưu hàm javascript vào một số thuộc tính tạm thời và ràng buộc nó khi bạn yêu cầu.

1

Tất cả các câu trả lời ở đây bây giờ đang lỗi thời - như jQuery 1,7 bạn nên sử dụng .off() như được giải thích on the official jQuery site

<!doctype html> 
 
<html lang="en"> 
 
<head> 
 
    <meta charset="utf-8"> 
 
    <title>off demo</title> 
 
    <style> 
 
    button { 
 
    margin: 5px; 
 
    } 
 
    button#theone { 
 
    color: red; 
 
    background: yellow; 
 
    } 
 
    </style> 
 
    <script src="https://code.jquery.com/jquery-1.10.2.js"></script> 
 
</head> 
 
<body> 
 
    
 
<button id="theone">Does nothing...</button> 
 
<button id="bind">Add Click</button> 
 
<button id="unbind">Remove Click</button> 
 
<div style="display:none;">Click!</div> 
 
    
 
<script> 
 
function flash() { 
 
    $("div").show().fadeOut("slow"); 
 
} 
 
$("#bind").click(function() { 
 
    $("body") 
 
    .on("click", "#theone", flash) 
 
    .find("#theone") 
 
     .text("Can Click!"); 
 
}); 
 
$("#unbind").click(function() { 
 
    $("body") 
 
    .off("click", "#theone", flash) 
 
    .find("#theone") 
 
     .text("Does nothing..."); 
 
}); 
 
</script> 
 
    
 
</body> 
 
</html>

+1

Tôi chấp nhận điều này, nhưng tôi muốn ví dụ đầu tiên được chỉnh sửa để gọi tắt() mà không có đối số, để hiển thị cách nó xóa tất cả các sự kiện được đính kèm (mà không cần phải tham chiếu đến chúng). Điều đó sẽ giải quyết chặt chẽ hơn câu hỏi ban đầu. – Ovesh

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