【问题标题】:How to trigger a custom javascript event in IE8?如何在 IE8 中触发自定义 javascript 事件?
【发布时间】:2012-11-06 06:22:29
【问题描述】:

我正在尝试在 IE8 上触发一个自定义事件,并从herehere 一起摆弄一个解决方案。但我无法让它工作......

我正在将 jquery mobile 与 requireJS 和谷歌分析一起使用。所以我正在跟踪 JQM pageshow 事件。然而,由于 requireJS 异步加载脚本,我对 pageshow 的绑定需要在 javascript“包装器”中进行,否则会产生错误,因为在解析 sn-p 时,jquery 和 jquery mobile 都不会被加载。

所以我在每一页的末尾都添加了这个:

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")}); 
}

当检测到时,我正在使用 pageshow 绑定触发我的分析 sn-p:

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]);
        }); 
    } 
}; 

所以要启动事件链,我需要在 JQM 准备好时触发 jqmReady。 JQM 使用他们的mobileinit 事件来表明这一点。所以在我的应用程序控制器初始化中,我像这样绑定到它:

$(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;
            });
    }
});

我试过只触发 $(window).trigger('jqmReady'),因为当mobileinit 触发时,jquery 可用。但是,在addEventListener 中创建的事件似乎无法像这样触发,所以我需要一个纯 JavaScript 的解决方案来触发 IE 中的自定义事件。

问题:
谁能给我指点一下如何正确触发 IE8 的 javascript 自定义事件?

【问题讨论】:

  • 为什么不将该触发器放在 $(document).ready() 中?为什么你需要它?
  • 因为jquery ~ $(document).ready() 在此代码运行时将不可用。在 requireJS 初始化之后,sn-p 就在页面上。所以(1)页面被解析,(2)requireJS触发器,(3)我的sn-p执行。当它发生时,jqueryjquery-mobile 都不会完全加载。所以,必须是 javascript-only。
  • 我不确定我是否关注了您的问题(因此是评论,而不是回答),但 dispatchEvent() 是否相关?
  • 哪部分不清楚?底线是我需要找到一种仅在 javascript 中触发自定义事件的方法,该方法适用于 IE8。让我检查一下dispatchEvent
  • @frequent, ah lol jquery mobile.... jquerymobile.com/test/docs/api/events.html 重要提示:使用 $(document).bind('pageinit'),而不是 $(document).ready()

标签: javascript jquery internet-explorer jquery-mobile requirejs


【解决方案1】:

好的,我终于明白了...这是它的工作原理:

1) 在正在加载的页面上设置 jqmReady 的监听器

// 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);
        }
    });
}

所以在 IE8 上,我不听自定义 jqmReady。相反,我为我的自定义属性 jqmReady 收听 onpropertychange

2) 然后在 mobileinit 上我触发如下:

 // 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++;
 };

好主意(感谢http://dean.edwards.name/weblog/2009/03/callbacks-vs-events/),也许其他人可以找到它的用途。

【讨论】:

【解决方案2】:

对于其他感兴趣的人,我已将此代码封装到静态 javascript 对象中

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]++;
    }
}

用法:

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

Event.trigger('myevent');

演示: http://jsfiddle.net/c5CuF/

【讨论】:

  • 不错。您可以添加一个.remove 方法来正确处理自定义事件。
  • 您应该在要点中阐明您在第 34 行中所做的事情,以摆脱 eval 语句。 document.documentElement[eventName]++
猜你喜欢
  • 2015-04-18
  • 1970-01-01
  • 1970-01-01
  • 2014-10-26
  • 1970-01-01
  • 1970-01-01
  • 2019-09-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多