2011-10-11 10 views
35

Questa domanda ha lo scopo di sviluppare plugin jQuery e altri snippet JavaScript autonomi che non richiedono la modifica di altri file di script per la compatibilità.Esiste un modo [universale] per richiamare un'azione predefinita dopo aver chiamato event.preventDefault()?

Sappiamo tutti che event.preventDefault() impedirà l'evento predefinito in modo che possiamo eseguire una funzione personalizzata. Ma cosa succede se vogliamo semplicemente ritardare l'evento predefinito prima di richiamarlo? Ho visto vari trucchi ninja specifici del caso e soluzioni alternative per ri-richiamare l'azione predefinita, ma come ho detto, il mio interesse è in un modo universale per riattivare l'impostazione predefinita e non gestire i trigger predefiniti su un caso caso per caso.

$(submitButton).click(function (e) { 

    e.preventDefault(); 

    // Do custom code here. 

    e.invokeDefault(); // Imaginary... :(
}); 

Anche per qualcosa di semplice come la presentazione del modulo, non sembra esserci una risposta universale. La soluzione alternativa $(selector).closest("form").submit() presuppone che l'azione predefinita sia l'invio di un modulo standard e non qualcosa di stravagante come una funzione __doPostBack() in ASP.NET. Alla fine di invocare callback ASP.NET, questo è il più vicino Sono venuto a un universale, la soluzione-it-and-forget-it set:

$(submitButton).click(function (e) { 

    e.preventDefault(); 

    // Do custom code here. 

    var javascriptCommand = e.currentTarget.attributes.href.nodeValue; 
    evalLinkJs(javascriptCommand); 
}); 


function evalLinkJs(link) { 
    // Eat it, Crockford. :) 
    eval(link.replace(/^javascript:/g, "")); 
} 

Suppongo che potrei iniziare a scrivere casi speciali da gestire collegamenti normali con un reindirizzamento window.location, ma poi stiamo aprendo una nuova lattina di worm - accumulando sempre più casi per il richiamo di un evento predefinito crea più problemi che soluzioni.

Quindi che ne dici? Chi ha il proiettile magico che stavo cercando?

+1

Io davvero non capisco quello che stai cercando di fare ... non lo fa l'evento codice di esecuzione eseguito * prima * si verifica l'azione predefinita (ad es. il codice del gestore di eventi 'submit' verrà eseguito prima che il modulo sia effettivamente inviato ... non è quello che stai cercando di ottenere?) –

+2

Il tuo codice personalizzato è asincrono? questo potrebbe spiegare perché ritieni di aver bisogno di un tale metodo, ma anche avere quel metodo immaginario non risolverà il tuo problema. – agradl

+1

Hai sicuramente bisogno di essere più chiaro su ciò che vuoi. Se si desidera eseguire il codice all'interno del gestore, tale codice viene comunque eseguito prima del comportamento "predefinito". –

risposta

8

Date un'occhiata a questo:

Si potrebbe provare

if(!event.mySecretVariableName) { 
    event.preventDefault(); 
} else { 
    return; // do nothing, let the event go 
} 

// your handling code goes here 
event.originalEvent.mySecretVariableName = "i handled it"; 

if (document.createEvent) { 
    this.dispatchEvent(event.originalEvent); 
} else { 
    this.fireEvent(event.originalEvent.eventType, event.originalEvent); 
} 

Utilizzando questa risposta: How to trigger event in JavaScript? e il riferimento evento jQuery: http://api.jquery.com/category/events/event-object/

Tag l'oggetto evento si riceve quindi se si riceverlo di nuovo non loop.

1

Non è possibile come JamWaffles ha già dimostrato. Semplice spiegazione del perché è impossibile: se riattivi l'azione predefinita il tuo listener di eventi intercetta ancora e hai un ciclo infinito.

E questo

click(function (e) { 
    e.preventDefault(); 
    // Do custom code here. 
    e.invokeDefault(); // Imaginary... :(
}); 

è lo stesso in questo modo (con la funzione immaginario).

click(function (e) { 
    // Do custom code here. 
}); 

Sembra che si desideri manipolare l'URL dell'elemento su cui si fa clic. Se lo fai in questo modo funziona perfettamente. Example.

5

Non chiamare preventDefault() in primo luogo. Quindi l'azione predefinita verrà eseguita dopo il gestore di eventi.

+9

Questo è il risposta corretta a condizione che non sia necessario eseguire la gestione predefinita in modo asincrono dopo la gestione personalizzata. – Jacob

4

Questo dovrebbe funzionare. Ho provato solo in Firefox però.

<html> 
<head> 
<script> 
    window.addEventListener("click",handleClick,false); 
    function handleClick(e){ 
     if (e.useDefault != true){ 
      alert("we're preventing"); 
      e.preventDefault(); 
      alert(e.screenX); 
      //Firing the regular action 
      var evt = document.createEvent("HTMLEvents"); 
      evt.initEvent(e.type,e.bubbles,e.cancelable); 
      evt["useDefault"] = true; 
      //Add other "e" attributes like screenX, pageX, etc... 
      this.dispatchEvent(evt); 
     } 
     else{ 
      alert("we're not preventing"); 
     } 
    } 
</script> 
</head> 
<body> 

</body> 
</html> 

Ovviamente, è necessario copiare anche tutti gli attributi delle variabili evento precedenti. Non ho codificato quella parte, ma dovrebbe essere abbastanza facile.

+2

+1 Questo è l'approccio corretto. Dovresti tentare di creare il tipo corretto di eventi - vedi https://developer.mozilla.org/en-US/docs/DOM/document.createEvent – chowey

0

avevo bisogno di disabilitare un tasto dopo il clic e quindi generare l'evento di default, questa è la mia soluzione

$(document).on('click', '.disabled-after-submit', function(event) { 
    event.preventDefault(); 
    $(event.currentTarget).addClass('disabled'); 
    $(event.currentTarget).removeClass('disabled-after-submit'); 
    $(event.currentTarget).click(); 
    $(event.currentTarget).prop('disabled', true); 
}); 
Problemi correlati