I'm trying to fire a custom event on IE8 and fiddling a solution together from here and here. But I cannot get it to work...
I'm using jquery mobile with requireJS and google analytics. So I'm tracking the JQM pageshow
event. However since requireJS loads scripts async, my binding to pageshow needs to be made in a javascript "wrapper", otherwise it will produce an error, because neither jquery nor jquery mobile will have been loaded by the time the snippet is parsed.
So I'm doing including this at the end of every page:
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")});
}
And when detected, I'm firing my analytics snippet with the pageshow binding:
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]);
});
}
};
So to kick of the event chain, I need to trigger jqmReady
when JQM is ready. JQM uses their mobileinit
event to indicate just that. So inside my application controller init, I'm binding to it like so:
$(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;
});
}
});
I have tried just triggering $(window).trigger('jqmReady'), because when mobileinit
triggers, jquery is available. However it seems events created in addEventListener
can not be triggered like this, so I need a javascript-only solution to trigger a custom event in IE.
Question:
Can someone give me a pointer on how to trigger a javascript custom event for IE8 correctly?
Definition and Usage. The trigger() method triggers the specified event and the default behavior of an event (like form submission) for the selected elements. This method is similar to the triggerHandler() method, except that triggerHandler() does not trigger the default behavior of the event.
The dispatchEvent() method of the EventTarget sends an Event to the object, (synchronously) invoking the affected EventListener s in the appropriate order. The normal event processing rules (including the capturing and optional bubbling phase) also apply to events dispatched manually with dispatchEvent() .
Ok, I finally understand... here is how it works:
1) setting the listener for jqmReady on the page being loaded
// 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);
}
});
}
So on IE8 I'm not listening for custom jqmReady
. Instead I listen for onpropertychange
for my custom property jqmReady
2) Then on mobileinit I'm triggering like this:
// 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++;
};
Nice idea (credit to http://dean.edwards.name/weblog/2009/03/callbacks-vs-events/), maybe someone else can find a use for it.
For anyone else interested, I've wrapped up this code into a static javascript object
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]++;
}
}
usage:
Event.listen('myevent', function () {
alert('myevent triggered!');
});
Event.trigger('myevent');
Demo: http://jsfiddle.net/c5CuF/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With