最近参与了一个项目,我的同事在开发一个ActiveX对象,我帮他编写JS脚本来调用这个对象,其中碰到蛮多问题,最难的就是如何响应由ActiveX对象返回的对象事件。正好,现在一起总结一下。

首先,我来介绍一下COM组件,以便说明js如何响应

    COM组件
        方法:   
                  void init()                    //初始化对象
                  Project createProject()        //创建一个Project类型的对象并返回
        事件:
                  onInit( int_code )             //当init成功后触发
     Project类的结构:
        方法:
                  void init()                     //初始化Project对象
        事件:
                  onInit( int_code )              //当init成功后触发

然后,我们在网页里创建一个ActiveX对象

<object id="myobj" classid="CLSID:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"></object>

然后,我们定义全局的变量obj和project,来保存对象的实例,并调用他们的相关方法

var obj = null;                                    //全局对象
var project = null;                                //Project对象
window.onload = function(){
    obj = document.getElementById('myobj');        //获取对象
    obj.init();                                    //初始化对象
    project = obj.createProject();                 //创建project对象
    project.init();                                //调用project对象的方法
};

最常见的对象事件响应方法

最常见的莫过于使用script event for的标签语法来响应对象事件了,Windows Media Player就是这样做的

<script language="Javascript" event="onInit( code )" for="myobj">  
if ( code == 0 )
{
    //Todo:
}
</script>

for属性指定了这个事件响应的对象是myobj,注意,这里要写object标签的id,不能是js变量
event属性指定了要响应哪个事件,这里是onInit事件。

如何响应ActiveX对象返回的对象事件

现在问题来了,我们调用了createProject方法,得到了一个project对象。这个对象也有事件,那么这时应该如何来响应呢?
显然,用之前的script event for的方法是不行的,因为for属性不能指定js变量的值。网上搜索了一下,找到了一种很特别的方法,就是用双冒号来定义函数名,于是,修改程序如下:

var project = obj.createProject();
function project::onInit( code )
{
    if ( code == 0 )
    {
        //Todo:
    }
}

不过,运行后有报错,说project未定义,想起来,js会优先执行function这个函数定义,也就是说先定义函数,然后才执行语句。所以,function必须在project创建成功以后才能定义,因此,修改程序如下:

var project = createProject();
var fn = function(){  //定义一个函数,这个函数内部会定义我们的回调函数
    //回调函数
    function project::onInit( code )
    {
        if ( code == 0 )
        {
            //Todo:
        }
    }
};
fn();    //执行这个函数,也就是定义回调函数

运行了一下,确实能响应了。

后记

不知大家看到 function project::onInit( code ) 这样的写法,是不是觉得很奇怪?我看到这种写法以后,很吃惊,因为我从没看到过javascript有这样的语法,这看上去像是定义一个静态函数,又像是在project命名空间中定义一个函数。于是我测试了一下,发现firefox并不能识别这样的函数定义,会报语法错误,说明这个不是标准javascript的写法,是IE-Only的写法。难道是JScript的语法?我又把JScript的手册从头到尾看了一遍,也没看到类似的语法。上微软的MSDN,也没有找到双冒号的语法参考。不过,我在一个论坛里,看到了这样一段话

A second script block that defines your event handler based on the global variable.  This has to be a separate script block, and the object has to be defined before this script block evaluates.  Syntax is "function object::Event(params)", where "object" is the name of the variable containing the object, "Event" is the name of the even to which you're subscribing, and "params" is the set of parameters the event handler expects.

或许这种写法就是为了实现ActiveX的event handler而准备的吧

js捕获activex事件的更多相关文章

  1. js 捕获型事件

    true 为捕获型事件 false 为冒泡型事件

  2. js捕获回车事件,并且获取每一条输入内容

    <body> <div style="width: 200px; height: 20px;"> <textarea id="inputVa ...

  3. js中冒泡事件和捕获事件

    js中冒泡事件和捕获事件: 冒泡事件:冒泡事件是从里向外,即是从被绑定元素开始一直向外到达页面的所有祖先元素都会被触发,这 一过程被称为事件冒泡.这个事件从原始元素开始一直冒泡到DOM树的最上层 捕获 ...

  4. JS中事件绑定函数,事件捕获,事件冒泡

    1 事件绑定:事件与函数绑定以及怎么取消绑定 1.1 元素.onclick这种形式,如下: <div id="div1">aaa</div> <scr ...

  5. JS中的事件冒泡和事件捕获

    事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标(target). 事件冒泡阶段:事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签. 用图示表示如下: 1.冒泡事件: ...

  6. js中关于事件捕获与事件冒泡的小实验

    1.事件冒泡:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发. IE 5.5: div -> body -> document IE 6.0: div - ...

  7. js事件捕获,事件冒泡,事件委托以及DOM事件流

    一:DOM事件流: 事件流是从页面接收事件的顺序,DOM2级事件规定事件流包括三个阶段: ①事件捕获阶段:用意在于事件达到目标之前捕获它,在事件捕获阶段事件流模型:document→html→body ...

  8. JS中的事件绑定,事件捕获,事件冒泡以及事件委托,兼容IE

    转载请注明出处:http://www.cnblogs.com/zhangmingze/p/4864367.html   ● 事件分为三个阶段:   事件捕获 -->  事件目标 -->   ...

  9. JS事件捕获和事件冒泡

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; line-height: 19.0px; font: 14.0px "Helvetica Neue" ...

随机推荐

  1. Using SMOTEBoost(过采样) and RUSBoost(使用聚类+集成学习) to deal with class imbalance

    Using SMOTEBoost and RUSBoost to deal with class imbalance from:https://aitopics.org/doc/news:1B9F7A ...

  2. Struts2与OGNL

    Action会自动放入值栈,成员变量会自动放入root区 如果是方法中的对象 要放入值栈 push()或者getRoot().push(); 界面取值  直接用对象的属性名进行取值

  3. 异常之: The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone.

    在 MySQL 中执行命令试下: set global time_zone=’+8:00’  设置为东8区 就不报错了. show variables like '%time_zone%'; 解释:在 ...

  4. STL stl_construct.h

    stl_construct.h // Filename: stl_construct.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog ...

  5. ffmpeg处理RTMP流媒体的命令和发送流媒体的命令(UDP,RTP,RTMP)

    将文件当做直播送至live ffmpeg -re -i localFile.mp4 -c copy -f flv rtmp://server/live/streamName     re限制输出速率, ...

  6. 启用Linux云平台oracle数据库实口令复杂性函数:PASSWORD_VERIFY_FUNCTION=NULL

    第一步:采用putty.exe登录数据库服务器. 输入IP后点击“Open”按钮: 第二步:登录对应的数据库实例. 执行:# su – oracle 查找:$ps -ef | grep pmon 找到 ...

  7. linux 在后台运行数据库导入导出命令

    nohup imp dbusername/password@orcl file=/home/20170928.dmp ignore=y log=/home/oracle/20170928.log fu ...

  8. 【C++】标准库sort函数的自定义排序

    自定义排序需要单独写一个compare函数 例1 LeetCode 056. Merge Intervals Given a collection of intervals, merge all ov ...

  9. Windows下安装MySQL-5.7.19

    下载MySQL-5.7.19版本,解压之后发现安装包不是一个exe文件: 于是网上找资料,发现了另外一种安装方法. 1.新建一个环境变量,我的电脑-属性-高级-环境变量-系统变量-新建 2.在系统变量 ...

  10. vs code 安装Scala

    首先本机要安装scala(官网肿么下不了,CSDN上面下的): 配置scala到环境变量PATH中(Scala的根目录): VS中安装以下扩展: 1. Scala: 2. Sbt: 3. Code R ...