9

Sto provando a generare un evento personalizzato su IE8 e a smanettare una soluzione insieme da here e here. Ma non riesco a farlo funzionare ...Come attivare un evento javascript personalizzato in IE8?

Sto usando jquery mobile con requireJS e google analytics. Quindi sto monitorando l'evento JQM pageshow. Tuttavia dal momento che requireJS carica gli script asincroni, il mio binding a pageshow deve essere fatto in un "wrapper" javascript, altrimenti produrrà un errore, perché né jquery né jquery mobile saranno stati caricati dal momento in cui lo snippet viene analizzato.

Così sto facendo compreso questo alla fine di ogni pagina:

if (document.addEventListener) { 
    document.addEventListener("jqmReady",function(){trigAnalytics("jqmReady");alert("FF detected")},false); 
} else if (document.attachEvent) { 
    document.attachEvent("jqmReady", function(){trigAnalytics("jqmReady");alert("IE detected")}); 
} 

E quando rilevato, sto sparando le mie analisi snippet con il legame del pageshow:

var trigAnalytics = function(trigger){ 
    $(document).on('pageshow','div:jqmData(role="page").basePage', function (event, ui) { 
     var url = location.href; 
     try { 
      hash = location.hash; 
      if (hash && hash.length > 1) { 
       _gaq.push(['_trackPageview', hash.substr(1)]); 
       _gaq.push(['_setCustomVar', 1, 'id_external', ########, 1 ]); 
      } else { 
       _gaq.push(['_trackPageview', url]); 
       _gaq.push(['_setCustomVar', 1, 'id_external', ########, , 1 ]); 
       _gaq.push(['b._trackPageview', url]); 
      } 
     } catch(err) { } 
    }); 
    if (typeof _gaq !== "undefined" && _gaq !== null) { 
     $(document).ajaxSend(function(event, xhr, settings){ 
      _gaq.push(['_trackPageview', settings.url]); 
      _gaq.push(['b._trackPageview', settings.url]); 
     }); 
    } 
}; 

Quindi, per calcio della catena di eventi, ho bisogno di innescare jqmReady quando JQM è pronto. JQM utilizza l'evento mobileinit per indicare proprio questo. Così dentro la mia applicazione del controller init, sto legame in questo modo:

$(document).bind("mobileinit", function() { 

    // non-IE OK 
    if (document.createEvent) { 
     evt = document.createEvent("Event"); 
     evt.initEvent("jqmReady", true, true); 
     document.dispatchEvent(evt); 

    } else if (document.createEventObject) { 
    // MSIE (NOT WORKING) 

     document.documentElement.evt = 0; // an expando property 
     document.documentElement.attachEvent("jqmReady", function() { 
      document.documentElement.evt = document.documentElement.evt + 1; 
      }); 
    } 
}); 

ho cercato solo innescando $ (window) .trigger ('jqmReady'), perché quando mobileinit trigger, jQuery è disponibile. Tuttavia sembra che gli eventi creati in addEventListener non possano essere attivati ​​in questo modo, quindi ho bisogno di una soluzione javascript-only per attivare un evento personalizzato in IE.

Domanda:
Qualcuno può darmi un puntatore su come attivare correttamente un evento personalizzato javascript per IE8?

+0

perché non mettere in quel grilletto $ (documento) .ready()? perché puoi averne bisogno? –

+0

Poiché 'jquery' ~ $ (document) .ready() non sarà disponibile quando viene eseguito questo codice. Lo snippet si trova nella pagina subito dopo l'inizializzazione di requireJS. Quindi la pagina (1) viene analizzata, (2) richiede triggerJS, (3) il mio frammento viene eseguito.Quando lo fa, né 'jquery' o' jquery-mobile' avranno pieno carico. Quindi, deve essere solo javascript. – frequent

+0

Non sono sicuro di seguire la tua domanda (quindi commentare, non rispondere) ma è ['dispatchEvent()'] (https://developer.mozilla.org/en-US/docs/DOM/element.dispatchEvent) di rilevanza? –

risposta

11

Ok, ho finalmente capito ... ecco come funziona:

1) impostando il listener per jqmReady sulla pagina da caricare

// non-IE: just create a listener for the custom event "jqmReady" 
if (document.addEventListener) { 
    document.addEventListener("jqmReady",function(){trigAnalytics("jqmReady");alert("FF detected")},false); 
// IE8 
} else if (document.attachEvent) { 

    // create a custom property name jqmReady and set it to 0 
    document.documentElement.jqmReady = 0; 
    // since IE8 does not allow to listen to custom events, 
    // just listen to onpropertychange 
    document.documentElement.attachEvent("onpropertychange", function(event) { 

     // if the property changed is the custom jqmReady property 
     if (event.propertyName == "jqmReady") { 
      trigAnalytics("jqmReady"); 
      alert("gotcha") 
      // remove listener, since it's only used once 
      document.documentElement.detachEvent("onpropertychange", arguments.callee); 
     } 
    }); 
} 

Così su IE8 non sto ascoltando personalizzato jqmReady. Invece Ascolto per onpropertychange per la mia proprietà personalizzata jqmReady

2) Poi, il mobileinit sto innescando in questo modo:

// non-IE 
if (document.createEvent) { 
     evt = document.createEvent("Event"); 
     evt.initEvent("jqmReady", true, true); 
     document.dispatchEvent(evt); 
} else if (document.createEventObject) { // MSIE 
     // just change the property 
     // this will trigger onpropertychange 
     document.documentElement.jqmReady++; 
}; 

Bella idea (credito per http://dean.edwards.name/weblog/2009/03/callbacks-vs-events/), forse qualcun altro può trovare un impiego per esso .

+2

Uno svantaggio di 'onpropertychange' è che non bolle comunque. Devi sapere in anticipo quale elemento ha la sua proprietà modificata. Maggiori informazioni su http://msdn.microsoft.com/en-us/library/ie/ms536956%28v=vs.85%29.aspx – dotnetCarpenter

6

Per chiunque altro interessato, ho avvolto il codice in un oggetto JavaScript statica

function Event() { 
} 

Event.listen = function (eventName, callback) { 
    if(document.addEventListener) { 
     document.addEventListener(eventName, callback, false); 
    } else {  
     document.documentElement.attachEvent('onpropertychange', function (e) { 
      if(e.propertyName == eventName) { 
       callback(); 
      }    
     }); 
    } 
} 

Event.trigger = function (eventName) { 
    if(document.createEvent) { 
     var event = document.createEvent('Event'); 
     event.initEvent(eventName, true, true); 
     document.dispatchEvent(event); 
    } else { 
     document.documentElement[eventName]++; 
    } 
} 

utilizzo:

Event.listen('myevent', function() { 
    alert('myevent triggered!'); 
}); 

Event.trigger('myevent'); 

Demo: http://jsfiddle.net/c5CuF/

+0

bello. È possibile aggiungere un metodo '.remove' per smaltire correttamente l'evento personalizzato. – frequent

+2

lo ha fatto [qui] (https://gist.github.com/frequent/6904575) – frequent

+0

nice one mate: D – Elliott

Problemi correlati