转载:http://www.cnblogs.com/walkingp/archive/2011/04/04/2003875.html
手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单
Chrome的更新速度可以说前无古人,现在我每天开机的第一件事就是打开Chrome检查是不是有了新版本。界面清爽、操作人性化、网络备份资料和快速的启动速度令我爱不释手,还有它拥有众多的扩展程序,相对于firefox的插件来说,数量上和质量上稍显不足,但相信chrome将会很快在扩展上超越firefox,firefox上内存占用上实在不令人满意,也许我使用firefox的一个原因就是因为firebug,不过相信chrome平台的类firebug插件也会很快出现。
Chrome的扩展开发十分简单,我们只需要掌握web开发的htm+CSS+Javascript,就能很快开发出自己的扩展。
你需要了解的内容
在开发前首先要掌握一些基础知识。
1、Chrome扩展文件
Chrome扩展文件以.crx为后缀名,在Google Chrome扩展官方网站下载扩展时,Chrome会将.crx文件下载到Chrome的Application Data文件夹的User Data\Temp下,一般是C:\Documents and Settings\User\Local Settings\Application Data\Google\Chrome\User Data\Temp,安装完成或者取消安装,该文件就会被删除。.crx实际上是一个压缩文件,使用解压文件打开这个文件就可以看到其中的文件目录,下图中是“关灯看视频”扩展的截图:
因此可以认为,我们实际上就是写一个Web应用,然后将按照Chrome的规定将一个快捷方式放在Chrome工具栏上。
2、Browser Actions(扩展图标)
把Browser Actions翻译成扩展图标不是很准确,但它的功能就是把你的应用显示在Chrome工具栏上。我们在上面看到一个文件manifest.json,就是使用这个文件来把相应的图标和其他参数注册到Browser Actions。比如下图中就是EverNote的扩展图标。
3、Page Actions(地址栏图标)
如果你熟悉一些Chrome插件的话,你一定会发现有些扩展的图标不是显示在地址栏的右边,而是显示在地址内部右方,这就是Page Actions地址栏图标。
可以看出上面中有三个Page Actions,图中我标出的是Chrome添加书签,现在你就会发现其实这个也是Chrome的扩展,只不是它是直接内置在Chrome的。
Page Actions与Browser Actions的区别就是Page Actions不是随时都是显示的,必须在特定的页面中这个功能才能使用。因此在开发中注意:如果不是全部页面中都能使用的功能请使用Page Actions方式。
4、popup弹出窗口
popup属于Browser Actions,当点击图标时出现这个窗口,可以在里面放置任何html元素,它的宽度是自适应的。当然,这个弹出窗口不会被Chrome拦截的:)
如下图中是evernote的popup窗口:
5、Background Pages后台页面
这个窗口不会显示,它是扩展程序的后台服务,它会一直保持运行。比如在一些需要数据保存程序中,如果当前用户关闭popup,就需要Background Pages来进行相应的操作。
自己动手做一个
我们以一个简单的任务管理程序来一步步讲解。
上图是界面实现,我们首先完成界面的显示部分,首先建立一个新文件夹,以扩展应用的名称为标题,我们这里的应用叫做MyTaskList。然后把找一个图标文件,放到文件夹中,也可直接右键下载我的这个图标:
图标文件不要小于19px*19px,但最好也不要超过这个尺寸,虽然大图它会自适应,但会使得应用文件变大。然后完成和未完成状态的两个图标放到资源文件中,可以建立任意文件夹放进去,因为CSS文件把定义它们的路径。
建立manifest.json来定义我们程序配置:
{ "name" : "MyTaskList" ,
"version" : "0.9.0" ,
"description" : "Management my everyday's task lists." ,
"browser_action" : {
"default_icon" : "icon.png" ,
"default_title" : "My Task List" ,
"default_popup" : "popup.html"
}
} |
其中name代表应用程序名,version代表版本号,description代表功能描述。这些在安装扩展后就能看到,见下图:
browser_action代表扩展图标段显示,它会定义图标地址、标题(也就是鼠标悬停提示)和默认的popup页面。我们这里定义的popup页面为popup.html。
接下来开始定义popup.html显示,它不需要使用<html>、<head>和<body>标签,可以直接写上样式、脚本和html。我们的popup.html源码为:
< style type="text/css">
*{margin:0;padding:0;} body{color:#333;overflow: hidden;margin: 0px;padding:5px;background: white;font-size:12px;} img{margin:0 4px;} #addItemDiv{color:#ccc;} .hide{display:none;} .show{display:block;} .taskItem{cursor:pointer;} input{width:100%;} label.on{width:12px; display:inline-block; height:12px; background:url(images/bg_task_on.gif) no-repeat 0px 2px;} label.off{width:12px; display:inline-block; height:12px; background:url(images/bg_task_off.gif) no-repeat 0px 2px;} </ style >
< div id="newItem" class="gray">添加新项</ div >
< div id="addDiv" class="hide">< input type="text" id="txtTitle" /></ div >
< div id="taskItemList">
< div class="taskItem">
< label class="on"></ label >< span class="taskTitle">新任务</ span >
</ div >
< div class="taskItem">
< label class="off"></ label >< span class="taskTitle">已完成任务</ span >
</ div >
</ div >
|
打开预览,样子就已经出来了:
这样我们文件就已经建立完成,文件列表如下:
现在就可以先尝试把它打包装到自己的Chrome里。
首先打开Chrome-工具-扩展程序,展开开发人员模式,打到“打包扩展程序”按钮:
点击“打包扩展程序…”,弹出打包选择文件窗口,在扩展程序根目标中找到我们建立的文件夹,私有密码文件第一次不用选择:
点击确定,它会在根文件夹同一级生成MyTaskList.crx和MyTaskList.pem,MyTaskList.pem是程序签名文件,以新版本的开发中还需要这个文件,不要删除它。把MyTaskList.crx拖进Chrome窗体内,就会把这个应用MyTaskList安装在Chrome里。
我们的这个简单的模型就能看到效果了,下一节我们就会完善其中的代码。
上一节我们已经讲了Chrome扩展的基础知识,并构建了基础的html,这一节我们将就html DOM添加部分添加脚本,即脚本在我们的popup页面中进行的操作,页面所产生的变化。
正常情况下数据处理加载完成状态,这些数据是从本地数据读取的。
点击“添加新项”,出现输入框,输入文字后回车提交数据:
添加完成后将数据存储,同时添加DOM元素:
考虑到功能最简化处理,点击已标为完成的任务,将提示“删除或重置为未完成”:
以上功能为最核心功能,可以在此基础上进行扩展,比如任务分组,修改任务,任务提醒,网络同步数据等等。
下面开始相应的脚本内容。
为了避免全局变量,使用匿名函数方式,所有事件处理及数据绑定均在此函数中进行,同时定义与jQuery中的$()类似的函数:
( function (){
var $= function (id){ return document.getElementById(id);}
})(); |
建立Tasks对象,定义show()函数和hide()函数,同时存储几个常用的DOM对象。
var Tasks = {
show: function (obj){
obj.className= '' ;
return this ;
},
hide: function (obj){
obj.className= 'hide' ;
return this ;
},
//存储dom
$addItemDiv:$( 'addItemDiv' ),
$addItemInput:$( 'addItemInput' ),
$txtTaskTitle:$( 'txtTaskTitle' ),
$taskItemList:$( 'taskItemList' )
} |
其中show()函数和hide()函数均使用了链式调用,每次执行此函数均会返回对象本身,这样对象就可以使用形如类似jQuery书写方式来使用此函数。
然后注册事件:
//..... //初始化 init: function (){
/*注册事件*/
//打开添加文本框
Tasks.$addItemDiv.addEventListener( 'click' , function (){
Tasks.show(Tasks.$addItemInput).hide(Tasks.$addItemDiv);
Tasks.$txtTaskTitle.focus();
}, true );
//回车添加
Tasks.$txtTaskTitle.addEventListener( 'keyup' , function (ev){
var ev=ev || window.event;
if (ev.keyCode==13){
//TODO:写入本地数据
Tasks.AppendHtml(task);
Tasks.$txtTaskTitle.value= '' ;
Tasks.hide(Tasks.$addItemInput).show(Tasks.$addItemDiv);
}
ev.preventDefault();
}, true );
//取消
Tasks.$txtTaskTitle.addEventListener( 'blur' , function (){
Tasks.$txtTaskTitle.value= '' ;
Tasks.hide(Tasks.$addItemInput).show(Tasks.$addItemDiv);
}, true );
//TODO:初始化数据,加载本地数据,生成html
}, //.... |
其中待完成部分为我们下一节将重点计到的html5的本地存储功能。再定义数据操作部分,先写上空白函数:
//.... //增加 Add: function (){
//TODO
}, //修改 Edit: function (){
//TODO
}, //删除 Del: function (){
//TODO
}, //... |
还需要初始化此函数使其执行并让匿名函数执行:
( function (){
var Tasks = {
//*** }
Tasks.init();
})(); |
好吧,以下就是本节中所要提到的全部代码:
代码中尚未实现的部分,我们将会在下节详细讲解其实现。
HTML5中的localStorage
localStorage与cookie类似,它是存储在客户端浏览器中的数据,它与cookie不同的一点是它没有时间限制。localStorage属于html5中的新特性,在浏览器支持localStorage统计中,Chrome4+、Firefox3.5+、IE8+、IE7兼容模式、Safari4+、Opera10.5+都是支持localStorage的。以下代码可以用于检测你的浏览器是否支持localStorage:
if (window.localStorage){
alert( '你的浏览器支持localStorage!' );
} else {
alert( '浏览器不支持localStorage!' );
} |
localStorage是以key/value方式来进行存储的,并且value只能是字符串形式,如果你要使用其他数据类型,需要进行相应的转换。设置和获取localStorage方法是使用localStorage.key,或localStorage[key]的形式,如:
localStorage.myName= 'walkingp' ;
localStorage[ 'mySite' ]= 'http://www.cnblogs.com/walkingp' ;
alert( 'name:' + localStorage.myName + '\rsite:' + localStorage[ 'mySite' ]);
|
修改其值就是重新设置相应的localStorage项取值。移除其值可以将其值设为null。
localStorage[ 'mySite' ]= null ;
|
也可以使用localStorage自带方法getItem()、setItem()和removeItem()来进行相应的获取、设置和移除localStorage项。
localStorage.setItem( 'age' , '24' );
var age=localStorage.getItem( 'age' );
alert( 'age:' + age); //age:24
localStorage.removeItem( 'age' );
age=localStorage.getItem( 'age' );
alert( 'age? ' + age); //age? null
|
可以使用clear()方法来清空所有localStorage。
对于不同域的localStorage,如本地和a.com,两者不影响对方。
关于localStorage本地存储大小,有人测试结果是其他浏览器为5M,Firefox没有作限制。而cookie一般只有几K,可见localStorage非常适合做稍大一些的数据存储,当然对于Chrome等扩展开发是非常合适的。
浏览器中的localStorage管理工具
Chrome和Safari均有自己的本地localStorage查看和管理工具,Firefox拥有第三方插件可以管理localStorage,Chrome中位于开发人员工具中的Resources左侧的Databases(可能稍早一点的版本位于单独出来的工具栏)。我们上面的localStorage在Chrome查看如下,利用这个工具可以修改或者删除相应项。
Safari中需要先在“偏好设置”、“高级”中将“在菜单中显示开发选项”勾选。
开始存储我们的localStorage
以上是我们需要了解的关于localStorage的知识,接下来就是把这个知识应用到我们Chrome扩展中。我们的数据存储分为两个部分,一是每项task需要存储的内容,它是以JSON的形式来存储的,形式如下:
task1:{ "id" :1, "task_item" : "新任务" , "add_time" : "2011-04-04T03:20:34.879Z" , "is_finished" : false }
|
task1表示key项,后台的JSON表示value项。意义很简单明了,其中is_finished表示当前任务是否已完成。当更新任务状态时就是将此项取值进行相应的更改。
还要放一个指向当前任务的数据,让它充当指针的作用,这样在添加新项时就不需要查询已有task项的id了。
'Tasks:index' :1
|
下面是我们代码的具体实现,首先开始初始化数据:
var Tasks = {
//指针
index:window.localStorage.getItem( 'Tasks:index' ),
//初始化
init: function (){
if (!Tasks.index){
window.localStorage.setItem( 'Tasks:index' ,Tasks.index=0);
}
//初始化数据
if (window.localStorage.length-1){
var task_list=[];
var key;
for ( var i=0,len=window.localStorage.length;i<len;i++){
key=window.localStorage.key(i);
if (/task:\d+/.test(key)){
task_list.push(JSON.parse(window.localStorage.getItem(key)));
}
}
for ( var i=0,len=task_list.length;i<len;i++){
Tasks.AppendHtml(task_list[i]);
}
}
},
//*** } |
然后是分别是增加项Add()、修改项Edit()和删除项Del()的方法:
//增加 Add: function (task){
//更新指针
window.localStorage.setItem( 'Tasks:index' , ++Tasks.index);
task.id=Tasks.index;
window.localStorage.setItem( "task:" + Tasks.index, JSON.stringify(task));
}, //修改 Edit: function (task){
window.localStorage.setItem( "task:" + task.id, JSON.stringify(task));
}, //删除 Del: function (task){
window.localStorage.removeItem( "task:" + task.id);
}, //*** |
其中的JSON.stringify是JSON将Javascript数据结构转换为JSON文本的方法,它与eval()为互操作。详情可见http://json.org/js.html 。
这样我们就将一个简单的Chrome扩展完成了,演示效果图如下:
当然它现在的功能还不够强大,我们还可以对它进行继续扩展,比如任务排序、任务分组、网络存储、定时提醒等。
系列文章至此暂时结束,全部代码包括生成后.crx文件已经打包,下载请点击此处。可能已有代码有一些处理不完善的地方,欢迎大家一一指出,共同进步!