2009-05-21 27 views
15

Tôi đang cố sửa đổi tất cả các liên kết trên một trang để chúng thực hiện một số công việc bổ sung khi chúng được nhấp.JavaScript: Thêm trình xử lý onClick mà không ghi đè số hiện có

Một cách tiếp cận tầm thường có thể là một cái gì đó như thế này:

function adaptLinks() 
{ 
    var links = document.getElementsByTagName('a'); 
    for(i = 0; i != links.length; i++) 
    { 
     links[i].onclick = function (e) 
     { 
      <do some work> 
      return true; 
     } 
    } 
} 

Nhưng một số trong các liên kết đã có tài onClick handler mà cần được bảo tồn. Tôi thử như sau:

function adaptLinks() 
{ 
    var links = document.getElementsByTagName('a'); 
    for(i = 0; i != links.length; i++) 
    { 
     var oldOnClick = links[i].onclick; 
     links[i].onclick = function (e) 
     { 
      if(oldOnClick != null && !oldOnClick()) 
      { 
       return false; 
      } 
      <do some work> 
      return true; 
     } 
    } 
} 

Nhưng điều này không làm việc vì oldOnClick chỉ được đánh giá khi xử lý được gọi là (nó chứa giá trị của liên kết cuối cùng như thời điểm này).

+0

I have seen that nhiều nhiệm vụ tương tự aroun d ở đây được giải quyết bằng cách sử dụng jQuery. Tôi hiện đang xem xét nó như là nó có vẻ dễ dàng một số nhiệm vụ khác là tốt. – rluba

Trả lời

16

Bạn cần phải tạo ra một đóng cửa để bảo tồn onclick giá trị ban đầu của mỗi liên kết:

<a href="#" onclick="alert('hi');return false;">Hi</a> 
<a href="#" onclick="alert('there');return true;">There</a> 
<script type="text/javascript"> 
function adaptLinks() { 
    var links = document.getElementsByTagName('a'); 
    for (i = 0; i != links.length; i++) { 
     links[i].onclick = (function() { 
      var origOnClick = links[i].onclick; 
      return function (e) { 
       if (origOnClick != null && !origOnClick()) { 
        return false; 
       } 
       // do new onclick handling only if 
       // original onclick returns true 
       alert('some work'); 
       return true; 
      } 
     })(); 
    } 
} 
adaptLinks(); 
</script> 

Lưu ý rằng việc thực hiện điều này chỉ thực hiện việc mới onclick xử lý nếu xử lý onclick gốc trả về true. Đó là tốt nếu đó là những gì bạn muốn, nhưng hãy nhớ rằng bạn sẽ phải sửa đổi mã một chút nếu bạn muốn thực hiện xử lý onclick mới ngay cả khi trình xử lý gốc trả về false.

Thông tin thêm về đóng cửa tại comp.lang.javascript FAQ và từ Douglas Crockford.

+0

+1 cho gợi ý về đóng cửa. Ví dụ của tôi được thiết kế đặc biệt để thực thi chỉ khi trình xử lý ban đầu không hủy, vì vậy ví dụ của bạn phù hợp với độc đáo. – rluba

18

Đừng gán cho một event handler ngay: sử dụng đăng ký mô hình addEventListener/attachEvent thay vì (mà cũng có loại bỏ cặp!).

Giới thiệu tốt here.

+1

+1 cho trang Quirksmode. – outis

+0

Hoặc, bạn có thể sử dụng một thư viện javascript (/ tôi bình chọn cho jQuery) mà sẽ cho phép bạn làm tương tự với rất nhiều dễ dàng hơn. Nhưng bạn vẫn phải đi qua lý thuyết tại trang quirksmode. Nó hoàn toàn làm giàu linh hồn cho một nhà phát triển javascript. – jrharshath

+1

"Dễ" là tương đối. Tôi có thể bọc nội dung này theo phương pháp 5 dòng HOẶC tôi có thể tải xuống thư viện đa K. Một thư viện là tốt để có, nhưng không phải tại các chi phí của việc biết làm thế nào để thực sự làm một cái gì đó cho mình. Tôi sẽ không chống bình chọn jquery, tôi chỉ không quan tâm đến kneejerk. – annakata

4

Sử dụng trình bao bọc xung quanh addEventListener (trình duyệt hỗ trợ DOM) hoặc attachEvent (IE).

Lưu ý rằng nếu bạn muốn lưu trữ giá trị trong biến mà không ghi đè giá trị cũ, bạn có thể sử dụng closures.

function chain(oldFunc, newFunc) { 
    if (oldFunc) { 
    return function() { 
     oldFunc.call(this, arguments); 
     newFunc.call(this, arguments); 
    } 
    } else { 
    return newFunc; 
    } 
} 

obj.method = chain(obj.method, newMethod); 

Trong Aspect Oriented Programming, điều này được gọi là "advice".

0

cách đặt oldClick = links[i].onclick or an empty function. Giống như rất

var oldOnClick = links[i].onclick || function() { return true; }; 

links[i].onclick = function (e) 
    { 
     if (!oldOnClick()) 
      return false; 
     //<do some work> 
     return true; 
    } 

Hoặc bạn có thể sử dụng attachEventaddEventListener như những người khác đã đề nghị

function addEvent(obj, type, fn) { 
     if (obj.addEventListener) 
       obj.addEventListener(type, fn, false); 
     else if (obj.attachEvent) 
       obj.attachEvent('on' + type, function() { return fn.apply(obj, [window.event]);}); 
} 

và sử dụng như vậy

addEvent(links[i], 'click', [your function here]); 
+0

Nó không giải quyết được vấn đề mà oldOnClick được đánh giá khi xử lý được gọi và không khi nó được viết. Plus: Nó không trả về false nếu xử lý onclick cũ trả về false (để ngừng liên kết hoạt động). – rluba

+0

Ah, tôi hiểu vấn đề tốt hơn. Bạn không thể trả về false nếu oldOnClick trả về false? –

0

Sử dụng JQuery, đoạn code sau hoạt động:

function adaptLinks(table, sortableTable) 
{ 
    $('a[href]').click(function (e) 
    { 
     if(!e.isDefaultPrevented()) 
     { 
      <do some work> 
     } 
    }); 
} 

Điều này đòi hỏi phải sử dụng thêm một thư viện nhưng tránh một số vấn đề tồn tại với addEventListener/attachEvent (giống như vấn đề thứ hai với this references).

Có chỉ là một cái bẫy: nếu bản gốc handler onClick được gán sử dụng "bình thường" JavaScript, dòng

... 
if(!e.isDefaultPrevented()) 
... 

sẽ luôn giải quyết để đúng, ngay cả trong trường hợp xử lý ban đầu hủy bỏ sự kiện bằng cách trả về false. Để khắc phục điều này, trình xử lý ban đầu cũng phải sử dụng JQuery.

0

Chức năng này nên được sử dụng (nghe sự kiện tiếp cận):

function addEventListener(element, eventType, eventHandler, useCapture) { 
    if (element.addEventListener) { 
     element.addEventListener(eventType, eventHandler, useCapture); 
     return true; 
    } else if (element.attachEvent) { 
     return element.attachEvent('on' + eventType, eventHandler); 
    } 
    element['on' + eventType] = eventHandler; 
} 

hoặc bạn có thể tiết kiệm một số mã khác thêm chức năng này (nếu bạn cần thêm người nghe cùng một sự kiện với nhiều yếu tố):

function addClickListener(element) { 
    addEventListener(element, 'click', clickHandler, false); 
} 
Các vấn đề liên quan