2010-05-14 11 views
32

Chciałbym usunąć ALL handlerów dla danego typu zdarzenia. Powiedzmy, że dodałem dwa razy "zdarzenie onclick" do przycisku, a teraz chciałbym powrócić do pierwotnego stanu, w którym do przycisku nie ustawiono obsługi zdarzeń.Czy można usunąć wszystkie programy obsługi zdarzeń danego elementu w javascript?

Jak mogę to zrobić?

PS: Znalazłem metody removeEventListener (non-IE)/detachEvent (IE), ale funkcje chcą, żebym przekazał jako parametr funkcję, która obsługuje wydarzenie, które wydaje mi się dość niezgrabne, ponieważ musiałbym przechowywać funkcje gdzieś.

EDIT: http://ejohn.org/blog/flexible-javascript-events/ - Obecnie używam tego kodu

+1

Czy używasz wbudowanego atrybutu onclick? – Mottie

+0

+1 Świetne pytanie. –

+0

Lepszą, bardziej bezpośrednią opcją jest użycie rozwiązania @ jiggy http://stackoverflow.com/questions/803936/how-to-clear-remove-javascript-event-handler – chowey

Odpowiedz

7

http://www.quirksmode.org/js/events_advanced.html - "Które procedury obsługi zdarzeń są zarejestrowane?" - wydaje się, że nie jest możliwe bez DOM 3 poziomie :-(

EDIT: Mam wymyślić ten kod pasuje ona do moich potrzeb Może to będzie pomocne dla kogoś innego

Javascript:

... strona
function DomLib() { 


} 


/** 
* Based on: http://ejohn.org/blog/flexible-javascript-events/ 
* Function that register event and enables it to be removed without explicitly giving the function definition 
*/ 
DomLib.prototype.regEventEx = function (el, eventName, funct) { 

    if (el.attachEvent) { 
    el['e'+eventName+funct] = funct; 
    el[eventName+funct] = function(){el['e'+eventName+funct](window.event);} 
    el.attachEvent('on'+eventName, el[eventName+funct]); 
    } else {  
    el.addEventListener(eventName, funct, false); 
    } 

    if(!el.eventHolder) el.eventHolder = []; 
    el.eventHolder[el.eventHolder.length] = new Array(eventName, funct); 
} 

DomLib.prototype.removeEvent = function (obj, type, fn) { 
    if (obj.detachEvent) { 
    obj.detachEvent('on'+type, obj[type+fn]); 
    obj[type+fn] = null; 
    } else { 
    obj.removeEventListener(type, fn, false); 
    } 
} 


DomLib.prototype.hasEventEx = function (el, eventName, funct) { 

    if (!el.eventHolder) { 
    return false; 
    } else { 
    for (var i = 0; i < el.eventHolder.length; i++) { 
     if (el.eventHolder[i][0] == eventType && String(el.eventHolder[i][1]) == String(funct)) { 
     return true; 
     } 
    } 
    } 
    return false; 
} 

/** 
* @return - returns true if an event was removed 
*/ 
DomLib.prototype.removeEventsByTypeEx = function (el, eventType) { 

    if (el.eventHolder) { 

    var removed = 0; 
    for (var i = 0; i < el.eventHolder.length; i++) { 
     if (el.eventHolder[i][0] == eventType) {     
     this.removeEvent(el, eventType, el.eventHolder[i][1]); 
     el.eventHolder.splice(i, 1); 
     removed++; 
     i--; 
     } 
    } 

    return (removed > 0) ? true : false; 
    } else { 
    return false; 
    } 
} 

Testowanie HTML:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> 
<html> 
<head> 
<meta http-equiv="Expires" content="Fri, Jan 01 1900 00:00:00 GMT"> 
<meta http-equiv="Pragma" content="no-cache"> 
<meta http-equiv="Cache-Control" content="no-cache"> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
<meta http-equiv="Lang" content="en"> 
<meta name="author" content=""> 
<meta http-equiv="Reply-to" content="@.com"> 
<meta name="generator" content="PhpED 5.8"> 
<meta name="description" content=""> 
<meta name="keywords" content=""> 
<meta name="creation-date" content="01/01/2009"> 
<meta name="revisit-after" content="15 days"> 
<title>DomLibTest</title> 
<link rel="stylesheet" type="text/css" href="my.css"> 
<!-- FILL IN: Location of your jQuery library --> 
<script type="text/javascript" src="jQuery/jQuery-current.js"></script> 
<!-- FILL IN: Plugin for debugging ... http://www.ecitadel.net/blog/2009/12/08/developing-jquery-use-dump-instead-alert --> 
<script type="text/javascript" src="jQuery/jQuery.dump.js"></script> 
<script type="text/javascript" src="DomLib.js"></script> 
</head> 
<body> 

    <div id="testElem-1"></div> 
    <script type="text/javascript"> 
    <!-- 

    var domLib = new DomLib(); 

    function removeTest(el) { 

     var funct = function() { alert("#1: How Are You?");}; 
     var funct2 = function() { alert("#2: How Are You?");};     

     domLib.regEventEx(el, "click", funct); 
     domLib.regEventEx(el, "mousemove", funct2); 
     domLib.regEventEx(el, "mousemove", funct2); 
     domLib.regEventEx(el, "mousemove", funct2); 

     $.dump(el.eventHolder);  
     domLib.removeEventsByTypeEx(el, "mousemove");  
     $.dump(el.eventHolder); 
    } 

    removeTest(document.getElementById('testElem-1')); 

    --> 
    </script> 
</body> 
</html> 
5

Według this thread, można użyć cloneNode rozebrać wszystkie detektory zdarzeń z elementu JavaScript, tak:

var new_element = old_element.cloneNode(true); 
old_element.parentNode.replaceChild(new_element, old_element); 
+1

Tak, ale następujące zdanie brzmi: Wierzę, że attachEvent działa nawet wtedy, gdy element jest klonowany, więc nie jestem pewien, co zrobiłbyś dla użytkowników Internet Explorera. –

8

Może dobrym pomysłem jest użycie jQuery lub podobnej struktury do zarządzania wszystkimi programami obsługi zdarzeń. To daje łatwy w obsłudze, funkcje dyskretnych do dodawania i usuwania programów obsługi zdarzeń:

$(...).bind('click', function() { ... }); 
$(...).unbind('click'); 
// or, to unbind all events: 
$(...).unbind(); 
+0

Chciałbym zrozumieć, jak to działa. Czy po prostu przechowuje funkcje gdzieś i unbind() po prostu przejrzyj listę funkcji i wywołaj removeEventListener? –

+2

Przechowuje listę zdarzeń wewnętrznie – ThiefMaster

+0

'$ (" * "). Unbind();' usunie wszystkie Event Handlers wszystkich elementów, jeśli próbujesz to zrobić. – palswim

-6

O ile mi wiadomo, nie można dodać dwa programy obsługi onclick do elementu w ogóle.

Powiedz, że obiekt jest elementem, a właściwość onclick obiektu jest uważana za funkcję, a następnie wywoływana jako metoda w momencie wystąpienia tego zdarzenia. Jeśli to nie działa, nic się nie stanie.

JavaScript odziedziczony po Schemacie bardzo interesująca właściwość, w JavaScript, nie definiuje się funkcji jak w PHP lub C. Tworzysz anonimowe funkcje i przechowujesz je w zmiennej. JavaScript to "Lisp-1", nie ma identyfikatorów funkcji, są zmienne, które mogą zawierać cyfry, tablice i funkcje.

function name(arg) {return arg;} 

Czy jeśli się nie mylę naprawdę cukier dla:

name = function(arg) {return arg;}; 

„name” tutaj jest zmienna, możemy również ponownie asign to bez względu na to, jak zdefiniowano tę funkcję. W przeciwieństwie do modelu obiektowego Java, w JavaScript, "metoda" jest czysto właściwością, zmienną, która po prostu posiada funkcję, która może lub nie może używać słowa kluczowego "to". Dlatego nie możesz mieć dwóch zdarzeń onclick w tym samym czasie. Środowisko wykonawcze po prostu wywołuje właściwość (która ma zawierać funkcję) elementu o nazwie "onclick" za każdym razem, gdy go klikniesz. Zobacz to samo zachowanie typu ad hoc, nazywając "main", aby uruchomić program.

Aby przypisać wiele procedur obsługi zdarzeń, należy użyć funkcji z efektem ubocznym, np..

obj.onclick = function {firstEvent();secondEvent();} 

Aby je zmienić lub usunąć, ponownie przyporządkowujemy lub odznaczamy je tak, jak każdą zmienną.

obj.onclick = null; 

A w przypadku musimy powoływać się na to zachowanie w inny sposób:

obj.onclick(); 

Możemy również skorzystać z tej funkcji, w tym oczywiście zmienić sam obiekt lub go odwołać.

Edytuj: O, zaczekaj, widzę teraz, że masz na myśli wiele przycisków.

Cóż, to po prostu zebrać wszystkie elementy, takie jak:

allElements = document.getElementsByTagName('*'); 

a następnie użyć pętli:

var i = 0; while(obj = allElements[i++]) obj.onclick = null; 

(a nie, że pojedyncze = nie jest literówka)

+0

http://pastebin.org/237133 - jest to przykład kodu, który wywołuje dwie procedury obsługi onclick dla jednego przycisku. (Testowane w Firefoksie i Chrome) –

+0

Naprawdę nie mam tylko jednego przycisku. –

+4

-1 dezinformacja w pierwszym zdaniu. Dowiedz się, jak działa obsługa zdarzeń w JavaScript i naprawiaj wpis, aby był +1 – naugtur

6

Jeśli masz tylko jeden element dziecięcej, pod rodzica elemencie (lub jeśli nie przeszkadza obsługi zdarzeń wszystkich rodzeństwa straciła zbyt):

elem.parentElement.innerHTML = elem.parentElement.innerHTML; 

Testowany w Chrome 49, FF 44, IE 11

Usuwa wszystkie 'addEventListener'-s.

Powiązane problemy