前言
在本插件中,popup
页面以及其他前端页面的启动都差不多。
ps: 也有一些小差别,就是Safari
下 popup
页面和其他的前端页面获取background
对象的形式不一样。浏览器 extension 插件开发系列(07) -- 获取各浏览器端的背景页
popup.html
以 popup.html
页面为例, 代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<head>
<meta charset="UTF-8">
<title>AirDroid</title>
<!-- build:css css/popup.min.css -->
<link rel="stylesheet" type="text/css" href="js/lib/bootstrap/css/bootstrap.css"/>
<link rel="stylesheet" type="text/css" href="js/lib/bootstrap/css/bootstrap-theme.css"/>
<link rel="stylesheet" type="text/css" href="styles/css/popup.css"/>
<!-- /build -->
</head>
<body>
<!-- build:js js/libs.min.js -->
<script type="text/javascript" src="js/lib/jquery/jquery.js"></script>
<script type="text/javascript" src="js/lib/jquery/jquery.toast.js"></script>
<script type="text/javascript" src="js/lib/jquery/jquery.clipboard.js"></script>
<script type="text/javascript" src="js/lib/underscore/underscore.js"></script>
<!-- /build -->
<!-- build:js js/popup.min.js -->
<script type="text/javascript" src="js/util/tplHelper.js"></script>
<!--<script type="text/javascript" src="tpls/jst.js"></script>-->
<script type="text/javascript" src="js/web/base.js"></script>
<script type="text/javascript" src="js/web/popup.js"></script>
<script type="text/javascript" src="js/lib/bootstrap/js/bootstrap.js"></script>
<!-- /build -->
</body>
这边除了 base.js
和 popup.js
这个两个业务逻辑js,其他都是第三方库,因此只要看这两个js就行了。其中 popup
又是继承 base
,因此先看 base
这个基类。
base.js 代码
1 | ; |
其实base
主要就做两件事:
- 获取背景页的对象
- 建立前端与背景页相互通信的事件驱动
1.获取背景页的对象。
获取各自浏览器的背景页对象(以下伪代码) 浏览器 extension 插件开发系列(07) -- 获取各浏览器端的背景页1
2
3var bg = getBrowserBackgroundPage(); // 这时候就可以得到Airdroid这个对象
setUpBackgroundPage(bg); // 将获得的这个背景页的Airdroid对象赋给当前前端页面的Airdroid变量,还有一些其他的,比如server,account之类的
inited(args) // base初始化结束,轮到popup初始化
第一个步骤在之前的章节中有说过,这边就不提了。这边主要讲第二个步骤,即setUpBackgroundPage
。
在这个步骤中,除了将背景页的Airdroid对象
赋给前端的Airdroid对象
之后。更要对事件驱动的对象进行设置。即 eventObj
。
说到这个对象 eventObj
,就必须得说道base
要做的第二个事情,就是前端和背景页相互通信的事件驱动。
说是相互通信,但是为了更好的兼容各个浏览器,目前全部采用前端监听的方式, 由背景页来触发这个事件。 即 addListener
这个方法。比如监听用户登入,登出,消息过来之类的
1 | // 手机通知推送过来 |
而 addListener
代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15addListener: function(name, fun){
var self = this;
if(this.eventObj){
if(window.chrome || window.safari){
this.eventObj.addEventListener(name, function (event) {
_.isFunction(fun) && fun(event.detail);
},false);
}else{
// firefox
this.eventObj.on(name, function(event){
_.isFunction(fun) && fun(event.detail);
})
}
}
},
代码还是很好理解的, 就是对于Chrome
和Safari
,就采用 addEventListener
的方式来监听。如果是Firefox
的话,就采用on
的方式来监听。
那么问题来了,eventObj
这个对象是怎么来的,为什么会有两种不同的方法?? 其实这个对象eventObj
就是在setUpBackgroundPage
这个方法里面设置的,然后这边会根据不同的浏览器来处理:
Chrome
代码如下:1
this.eventObj = data;
代码最简单,直接将background的对象赋给eventObj
就行了。
因为在前端页面用background
的window
对象进行addEventListener
进行监听的话,如果是在背景页进行window.dispatchEvent
进行触发的话,是可以生效的。
Safari
代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41this.eventObj = data;
if(dispatcher){
// 说明是非popover页面
// 同时要绑定对应的事件触发器
var addSafariTriggerHandle = function(obj){
if(obj.funListenerObjs){
_.each(obj.funListenerObjs,function(funId,name){
// 重新定义函数
obj[name] = function(){
console.log("调用函数,函数名为%s, id为 %s", name, funId);
var defer = $.Deferred();
// 加入回调队列
var deferDoneId = _.uniqueId("defer_done_" + name + "_");
var deferFailId = _.uniqueId("defer_fail_" + name + "_");
self.funCbObj[deferDoneId] = function(data){
self.log(deferDoneId);
defer.resolve(data);
};
self.funCbObj[deferFailId] = function(data){
self.log(deferDoneId);
defer.resolve(data);
};
console.log("参数为==》" + JSON.stringify(Array.prototype.slice.apply(arguments)))
// 触发函数
safari.self.tab.dispatchMessage(funId,{
arg: Array.prototype.slice.apply(arguments),
done: deferDoneId,
fail: deferFailId
});
return defer;
};
})
}
_.each(obj,function(value,key){
if(_.isObject(value)){
addSafariTriggerHandle(value);
}
})
};
addSafariTriggerHandle(this.Airdroid);
}
如果是popup
页面的话,那就跟Chrome
一样,直接 eventObj=data
。 如果是其他的页面,即dispatcher
是有值的。那么就要绑定对应的触发器,这个触发器是跟background
的events事件模型
相挂钩的,后面讲到事件模型的时候,会讲到。
- Firefox 代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46// firefox 事件触发器
this.eventObj = fireFoxEvent;
// 同时要绑定对应的事件触发器
var addFireFoxTriggerHandle = function(obj){
if(obj.funListenerObjs){
_.each(obj.funListenerObjs,function(funId,name){
// 重新定义函数
// 这时候,要把组件的监听对象,传到page页面去
self.eventObj.emit('page_bind_handle',funId);
obj[name] = function(){
var defer = $.Deferred();
var deferDoneId = _.uniqueId("defer_done_" + name + "_");
var deferFailId = _.uniqueId("defer_fail_" + name + "_");
var deferAlwayId = _.uniqueId("defer_alway_" + name + "_");
// 一次性监听
self.eventObj.once(deferDoneId,function(data){
//self.log(deferDoneId);
defer.resolve(data.detail);
});
self.eventObj.once(deferFailId,function(data){
//self.log(deferFailId);
defer.reject(data.detail);
});
self.eventObj.once(deferAlwayId,function(data){
//self.log(deferAlwayId);
defer.reject(data.detail);
});
// 触发函数
self.eventObj.emit(funId,{
arg: Array.prototype.slice.apply(arguments),
done: deferDoneId,
fail: deferFailId,
always: deferAlwayId
});
return defer;
};
})
}
_.each(obj,function(value,key){
if(_.isObject(value)){
addFireFoxTriggerHandle(value);
}
})
};
addFireFoxTriggerHandle(this.Airdroid);
Firefox
的处理方式跟 Safari
不是 popup
页面的其他页面很像。也是跟background
的events模型
有关系,后面一起讲。
2.建立前端与背景页相互通信的事件驱动
具体查看: 浏览器 extension 插件开发系列(10) -- 事件驱动模型
系列文章:
浏览器 extension 插件开发系列(01) -- 前言和确认需求
浏览器 extension 插件开发系列(02) -- Chrome 插件的启动以及调试
浏览器 extension 插件开发系列(03) -- Firefox 插件的启动以及调试
浏览器 extension 插件开发系列(04) -- Safari 插件的添加以及调试
浏览器 extension 插件开发系列(05) -- Safari 插件申请开发者证书
浏览器 extension 插件开发系列(06) -- 各浏览器导航栏按钮的配置的点击出现的panel
浏览器 extension 插件开发系列(07) -- 获取各浏览器端的背景页
浏览器 extension 插件开发系列(08) -- 背景页启动和登录持久化
浏览器 extension 插件开发系列(09) -- popup以及其他前端页面的启动
浏览器 extension 插件开发系列(10) -- 事件驱动模型
浏览器 extension 插件开发系列(11) -- 登录模块(包括第三方登录和弹框)
浏览器 extension 插件开发系列(12) -- 实现右键菜单推送消息
浏览器 extension 插件开发系列(13) -- 实现消息过来出现桌面通知
浏览器 extension 插件开发系列(14) -- 点击reply出现回复小窗口
浏览器 extension 插件开发系列(15) -- chrome多文件上传(拖拽上传或者点击上传)
浏览器 extension 插件开发系列(16) -- Firefox 遇到的问题
浏览器 extension 插件开发系列(17) -- Safari 遇到的问题