不知道看到这篇文章的各位朋友们有没有用过遨游,遨游有一个很好的特性,并且这个特性是我特别喜欢的,就是鼠标手势,比如打开一个链接,直接把鼠标点到超链接上,然后按住拖动,就可以在一个新窗口中打开点的链接,这样就非常的快的打开链接,而不用按鼠标中键或者按ctrl然后点一下才打开链接,所以这是我特别喜欢的功能。
搜了一下,看了Firefox好像没有这样的功能,而有这样功能的几个插件都没有我想定制的特性(比如鼠标手势,从左到右移动鼠标就是返回),所以我决定自己写一个。
在Firefox中,浏览器可以添加事件,并添加属性,这些事件分别为draggesture,ondragover,ondragdrop,ondragexit,这四个事件分别对应的几个nsDragAndDrop对象(这是一个XPCOM对象)的几个事件,分别为startDrag,dragOver,drop和,dragExit四个事件,所以我们编写以下代码。
var DragUrLink =
{
OnMainLoad: function(){
try
{
getBrowser().addEventListener('draggesture',
function(event) {nsDragAndDrop.startDrag(event, DragObserver);} , true);
getBrowser().setAttribute('ondragover',
'nsDragAndDrop.dragOver(event, DragObserver)');
getBrowser().setAttribute('ondragdrop',
'nsDragAndDrop.drop(event, DragObserver)');
getBrowser().setAttribute('ondragexit',
'nsDragAndDrop.dragExit(event, DragObserver)');
}
catch(e)
{
//alert(e)
}
}
};
上面的代码可以添加事件,也可以添加属性,反正对象getBrowser(同gBrowser),所以起到的效果是一样的。在nsDragAndDrop对象的几个方法中,传递的参数都是event和一个类(如果javascript里面可以说成是类的话)或者对象,这些对象里面都要重写(如果可以叫重写的话)一些方法,而且这些方法是固定的,基本上玩不出什么花样,所以这里我就写了一个接口,提供给大家使用,如果你需要响应Drag和Drop方法的话,可以尝试用下面的代码。
//Copyright GuoJing http://www.shangducms.com
//如果不会可以直接Copy
var DragObserver = {
Cc : Components.classes,
url:"",
isend:1,
times:0,
onDragStart: function(e, aXferData, dragAction){
//拖动事件开始时
this.isend = 0;
},
onDragOver: function(e, aFlavour, aDragSession){
//拖动事件执行时
var transData = DragObserver
.getTransferData(aFlavour.contentType, aDragSession);
if(transData.dataObj.value){
var DataObj = transData.dataObj.value
.QueryInterface(Components.interfaces.nsISupportsString);
var sourceUri = DataObj.data.substring(0, transData.len.value);
//拖动的数据是以\n分割
var DragData = sourceUri.split("\n");
//获取拖动的数据
this.url = DragData[0];
}
},
onDrop: function (e, aDropData, aDragSession){
},
unInit: function(){
},
onDragExit: function(e, aDragSession){
//当结束拖动时发生
if(this.isend == 0)
{
DragObserver.reload();
}
//设置flag为1,那么下次结束拖动时就不会再操作了
//这里值得注意的是,一次拖动时会响应多次拖动结束事件
this.isend = 1;
},
reload:function()
{
//这里是结束时发生一次的方法
//if(DragObserver.IsContain(this.url,'http://'))
//{
//gBrowser.addTab(this.url);
//}
//openUILink("http://www.shangducms.com", null, false, true);
alert(this.url);
},
checkSession : function(){
},
canDrop : function(e, aDragSession){
},
getSupportedFlavours: function (){
//设置数据对象
var flavourSet = new FlavourSet();
flavourSet.appendFlavour("text/x-moz-url");
flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
flavourSet.appendFlavour("text/unicode");
flavourSet.appendFlavour("text/html");
return flavourSet;
},
getTransferData : function(aContentType, aDragSession){
//这里是获取拖动的数据,具体可以查nsITransferable接口
var transfer = this.Cc["@mozilla.org/widget/transferable;1"].
createInstance(Components.interfaces.nsITransferable);
transfer.addDataFlavor(aContentType);
aDragSession.getData (transfer, 0);
var Data = {};
Data.dataObj = new Object();
Data.len = new Object();
try{
transfer.getTransferData(aContentType, Data.dataObj, Data.len);
} catch (ex) {}
return Data;
},
IsContain:function(str,para)
{
var regex=new RegExp(para, 'g').exec(str);
if(regex)
{
//if the string contain the para
return true;
}
else
{
return false;
}
}
}
上述代码就实现了响应拖动的事件,看上去是不是很复杂很麻烦,其实确实很复杂很麻烦,我也是查了很多资料才知道要这么写的,注意其中一些方法是系统内部彼此调用的,感觉很像重写或者重载的感觉,所以虽然你不知道这个是怎么执行的,但是必须这么写。
其中有一些方法,这里我就不列举了,例如onDragStart,可以不写,但是不写就不会响应,还有名字和参数最好也要写成一致的。因为当浏览器响应的时候,会自动传递这些参数以便在浏览器钟使用或进行转换。这些事件响应过程分别为,开始拖动=》canDrop=》获取传递的数据=》过滤数据(getSupportedFlavours)=》onDragOver=》查看会话=》onDragExit,当然,这些步骤并不会响应一次,在移动的时候可能会响应多次。
看到这里,你应该觉得一个小小的功能实现起来太麻烦了,好在Firefox 3.5提供了更好的API,可以直接响应DragEnd方法,示例代码如下所示。
OnMainLoad: function(){
try
{
getBrowser().setAttribute('ondragend', 'DragUrLink.DoSomeThing(event)');
}
catch(e)
{
//出错处理
}
},
DoSomeThing:function(event)
{
//执行响应的事件
}
是不是非常简单?所以赶快升级到3.5吧,3.5的API和HTML5的支持更上一层楼了。
OK,最后,如果你还不能理解,就制作一个3.5的程序,如果你能搞定老的API的拖动效果,那么祝贺你,你比我强多了:),因为老的虽然可以实现,但是实现的太复杂了,用了好多类,所以我还是决定只支持3.5。
示例
Currently rated 5.0 by 1 people
- Currently 5/5 Stars.
- 1
- 2
- 3
- 4
- 5
Firefox Addon
firefox, extension, drag, and, drop, 扩展