2009-12-17 2 views
35

Làm cách nào để tạm thời tắt trình xử lý sự kiện onclick, (ưu tiên jQuery), sau khi sự kiện đã được kích hoạt?jQuery - Làm cách nào để tạm thời vô hiệu hóa trình xử lý sự kiện onclick sau khi sự kiện đã được kích hoạt?

Ví dụ:

Sau khi người dùng nhấp chuột vào nút và cháy chức năng này dưới đây, tôi muốn vô hiệu hóa các onclick người nghe, do đó không bắn cùng một lệnh để xem django tôi.

$(".btnRemove").click(function(){ 
    $(this).attr("src", "/url/to/ajax-loader.gif"); 
    $.ajax({ 
     type: "GET", 
     url: "/url/to/django/view/to/remove/item/" + this.id, 
     dataType: "json", 
     success: function(returned_data){ 
      $.each(returned_data, function(i, item){ 
       // do stuff      
    }); 
    } 
}); 

Thanks a lot,

Aldo

+0

tạm thời như thế nào? điều gì đã xảy ra trước khi bạn muốn chấp nhận các sự kiện nhấp một lần nữa? –

+9

(PS. Không cho phép yêu cầu GET thực hiện các thay đổi trạng thái.) – bobince

+2

@bobince: Ồ, nó sẽ không tuyệt vời nếu tất cả chúng ta đều tuân theo quy tắc đơn giản đó ... @OP: Xem thêm về những gì bob nói về (đáng sợ turgid văn xuôi) ở đây: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.2 –

Trả lời

64

Có rất nhiều cách để thực hiện. Ví dụ:

$(".btnRemove").click(function() { 
    var $this = $(this); 
    if ($this.data("executing")) return; 
    $this 
     .data("executing", true) 
     .attr("src", "/url/to/ajax-loader.gif"); 
    $.get("/url/to/django/view/to/remove/item/" + this.id, function(returnedData) { 
     // ... do your stuff ... 
     $this.removeData("executing"); 
    }); 
}); 

hoặc

$(".btnRemove").click(handler); 

function handler() { 
    var $this = $(this) 
     .off("click", handler) 
     .attr("src", "/url/to/ajax-loader.gif"); 
    $.get("/url/to/django/view/to/remove/item/" + this.id, function(returnedData) { 
     // ... do your stuff ... 
     $this.click(handler); 
    }); 
} 

Chúng tôi cũng có thể sử dụng đoàn kiện cho mã rõ ràng hơn và hiệu suất tốt hơn:

$(document).on("click", ".btnRemove:not(.unclickable)", function() { 
    var $this = $(this) 
     .addClass("unclickable") 
     .attr("src", "/url/to/ajax-loader.gif"); 
    $.get("/url/to/django/view/to/remove/item/" + this.id, function(returnedData) { 
     // ... do your stuff ... 
     $this.removeClass("unclickable"); 
    }); 
}); 

Nếu chúng ta không cần phải kích hoạt lại các handler sau khi nó đã được thực hiện, sau đó chúng ta có thể sử dụng phương thức .one(). Nó liên kết các trình xử lý chỉ được thực hiện một lần. Xem tài liệu jQuery: http://api.jquery.com/one

+0

Điều này làm việc cho tôi . Tôi có thể hủy bỏ nó một cách an toàn, bởi vì một khi phần công cụ làm kết thúc, nút hình ảnh bị phá hủy. – aldux

+3

Trong trường hợp đó, bạn nên sử dụng phương thức .one() để ràng buộc các trình xử lý chỉ được thực thi một lần. Xem tài liệu jQuery: http://docs.jquery.com/Events/one – thorn

+0

Vâng, tôi không biết về phương thức one(). Điều đó sẽ làm một cách thanh lịch hơn! Cám ơn. – aldux

5

tại sao không tắt nút? Bất kỳ lý do cụ thể mà bạn muốn vô hiệu hóa listner này một mình? BTB, từ mã của bạn, tôi thấy rằng bạn đang thực hiện cuộc gọi ajax. SO bạn đặc biệt muốn chặn người dùng cho đến khi cuộc gọi trở lại? Nếu có, bạn có thể thử blockUI, một plugin jQuery

1

Tôi khuyên bạn nên tắt nút, sau đó bật lại nó trong các thói quen hoàn thành Ajax của bạn (thành công hoặc không thành công, hãy nhớ). Nếu bạn lo lắng về trình duyệt không tôn trọng việc vô hiệu hóa nút, bạn có thể quay lại với cờ của riêng bạn trên nút (ví dụ: đặt thuộc tính được gọi là data-disabled, sử dụng tiền tố data- làm phương pháp hay và tương thích HTML5). Tuy nhiên, việc chặn thực sự gặp sự cố với trình duyệt không vô hiệu hóa nút, tôi có thể xem xét điều đó đủ tốt.

18

Bạn muốn tắt trình xử lý sự kiện nhấp chuột trong bao lâu? Một cách là hủy liên kết trình xử lý sự kiện bằng cách sử dụng số unbindhttp://docs.jquery.com/Events/unbind của jQuery.

Nhưng thực tiễn tốt nhất là không hủy liên kết một sự kiện chỉ để khôi phục sau đó. Sử dụng một boolean thay thế.

var active = true; 
$(".btnRemove").click(function(){ 
    if(active){ 
     return; 
    } 
    active = false; 
    $(this).attr("src", "/url/to/ajax-loader.gif"); 
    $.ajax({ 
     type: "GET", 
     url: "/url/to/django/view/to/remove/item/" + this.id, 
     dataType: "json", 
     success: function(returned_data){ 
     active = true; // activate it again ! 
     $.each(returned_data, function(i, item){ 
       // do stuff      
    }); 
    } 
}); 

chỉnh sửa: để được an toàn bạn cũng nên quan tâm đến những thói quen hoàn thành ajax khác (chỉ có ba là: success, error, completesee docs) hoặc khác active có thể ở lại sai.

+0

làm thế nào để thực hiện công việc này, hoạt động là gì, nhưng một boolean được đọc vào đầu – TStamper

+2

'hoạt động' vẫn giả cho đến khi yêu cầu ajax kết thúc với một thành công. trong thời gian đó, trình xử lý nhấp chuột ngay lập tức trả về ngay từ đầu, do đó, về cơ bản không phải là việc xử lý. – RamboNo5

+0

didnt catch that inside..thanks – TStamper

1

Bạn có thể thực hiện hành động trong nhấp chuột dựa trên giá trị boolean. Khi nó được nhấp, thay đổi giá trị boolean và sử dụng setTimeout() để thay đổi nó sau một vài giây. Điều đó có hiệu quả sẽ hạn chế người dùng nhấp vào nút chỉ một lần mỗi vài giây.

var isEnabled = true; 

$("a.clickMe").click(function(e){ 
    e.preventDefault(); 
    if (isEnabled == true) { 
    isEnabled = false; // disable future clicks for now 
    do_Something(); 
    setTimeout(function(){ 
     isEnabled = true; 
    }, 3000); // restore functionality after 3 seconds 
    } 
}); 
+0

Tôi thực sự thích cách tiếp cận này, rất đơn giản và ít chi phí. Cảm ơn Jonathan! –

1
var ajaxAction = function() { 
    var ele = $(this); 
    ele.unbind("click", ajaxAction); 
    ele.attr("src", "/url/to/ajax-loader.gif"); 
    $.ajax({ 
     type: "GET", 
     url: "/url/to/django/view/to/remove/item/" + this.id, 
     dataType: "json", 
     success: function(returned_data) { 
      $.each(returned_data, function(i, item) { 
      }); 
     }, 
     complete: function() { 
      ele.bind("click", ajaxAction); 
     } 
    }); 
} 
$(".btnRemove").click(ajaxAction); 
+0

Tôi thực sự sẽ thêm chính xác điều này. Sạch hơn nhiều để đặt tên nó và unbind/rebind nội bộ hơn tất cả các hoops khác được nhảy qua trong các ví dụ này. –

3

tôi sẽ thiết lập một biến toàn cầu để theo dõi các yêu cầu AJAX ...

var myApp = { 
    ajax: null 
} 

Và sau đó có chút này chút ma thuật để ngăn chặn đồng thời yêu cầu ...

// Fired when an AJAX request begins 
$.ajaxStart(function() { myApp.ajax = 1 }); 

// Fired when an AJAX request completes 
$.ajaxComplete(function() { myApp.ajax = null }); 

// Fired before an AJAX request begins 
$.ajaxSend(function(e, xhr, opt) { 
    if(myApp.ajax != null) { 
    alert("A request is currently processing. Please wait."); 
    xhr.abort(); 
    } 
}); 

Với cách tiếp cận này, bạn không cần phải quay lại mã của mình và sửa đổi mọi cuộc gọi AJAX duy nhất của bạn. (thứ mà tôi gọi là giải pháp "nối thêm")

+0

Kể từ jQuery 1.9, tất cả các trình xử lý cho [các sự kiện Ajax toàn cầu của jQuery] (http://api.jquery.com/category/ajax/global-ajax-event-handlers/), bao gồm cả các trình xử lý được thêm vào với .ajaxStart (), phải được đính kèm vào tài liệu. – ooXei1sh

2

Tôi sẽ sử dụng một lớp như 'ajax-running'. Sự kiện nhấp chuột sẽ chỉ được thực hiện nếu phần tử được nhấp không có lớp 'ajax-running'. Ngay khi bạn kết thúc cuộc gọi ajax, bạn có thể xóa lớp 'ajax-running' để nó có thể được nhấp lại.

$(".btnRemove").click(function(){ 
    var $button   = $(this); 
    var is_ajaxRunning = $button.hasClass('ajax-running'); 
    if(!is_ajaxRunning){ 
     $.ajax({ 
      ... 
      success: function(returned_data) { 
       ... 
       $button.removeClass('ajax-running'); 
      }); 
     }; 
    } 
}); 
1

Nếu bạn đăng bài qua ajax, bạn có thể tắt nút khi nhấp và bật sau khi quá trình hoàn tất. Nhưng nếu bạn đăng lại, bạn không thể tắt nút. Việc vô hiệu hóa nút sẽ khiến sự kiện nhấp chuột phía máy chủ không kích hoạt. Vì vậy, chỉ cần ẩn nút khi nhấp và hiển thị thông báo thân thiện với người dùng. Bài đăng trên how to disable asp.net button on postback sẽ giúp bạn.

0

bạn cũng có thể chỉ giấu nút (hoặc div chứa)

$(".btnRemove").click(function() { 
    $(this).hide(); 
    // your code here... 
}) 

và bạn chỉ có thể gọi .show() nếu bạn cần để hiển thị nó một lần nữa.

Cũng tùy thuộc vào trường hợp sử dụng của bạn, bạn nên cân nhắc sử dụng lớp phủ tải thay vì