Firefox扩展插件开发笔记(三)-发送Http请求获取数据

紧接着上次笔记写点,上次写了主要三个关键问题,这里主要解决第二个如何,发送翻译文本同时接收翻译数据本来想的是使用Ajax,后来有个跨域问题档在前面,看了很多解决跨域的方法感觉都不太理想,好吧还是看下英文文档用Add-on SDK中的API做吧,最后再把翻译显示面板html/css调教一下,就可以收工了,扩展插件下载地址

导航目录

  1. Add-on Script中使用Request请求翻译数据
    1.1 Request发送Http请求
    1.2 Add-on script和content script间传递消息
  2. Content Script中添加翻译结果面板
    2.1 添加翻译结果的面板
    2.2 与Add-on script间的消息传递

使用Request请求翻译数据

因为跨域的问题,所以这里使用Add-on SDK里的Request发送Http请求到Baidu API,相关API请求和数据格式课看下百度翻译的API文档,下面是构建的目录结构

|- data
    |- content.js   之前编写的content script文件
    |- jquery-1.11.2.min.js
|- lib
    |- main.js      Add-onscript文件
|- test
|- icon.png     扩展小图标
|- icon64.png       扩展大图标
|- package.json     扩展包描述文件

因此下面写的代码基本在lib/main.js中,也就是说是Add-on script,具体代码实现可以查看源代码:

源代码地址

Request发送Http请求

Request使用方法很简单,构造一个Request对象,构造函数里面传url和请求完成时接收数据的回调函数,再对该对象调用.get() 函数发起请求,可以像这样:

Request({
        url: addr,
        onComplete: function(response) {
            //To do what you want here
        }
    }).get();
}

为了以后方便调用,准备把发送请求封装到一个函数里边,函数参数为要翻译的文本和构造好的地址还有一个Worker(后面会说),像这样:

function onBaiduTrans(worker, text, addr) {
    var wikiaddr = "https://" + wikilan + ".wikipedia.org/w/index.php?useformat=mobile&title=" + text;
    Request({
        url: addr,
        onComplete: function(response) {
            if (!response.json) {
                worker.port.emit("get-transtext", [text, '<p>connect translate API faile</p>']);
                return;
            }
            var transTxt = '<p>';
            if (response.json.error_msg) {
                transTxt = '翻译出错了!';
            } else {
                for (var index in response.json.trans_result) {
                    transTxt += response.json.trans_result[index].dst;
                }
            }
            //console.log("translate:" + transTxt);
            worker.port.emit("get-transtext", [wikiaddr, transTxt+'</p>']);
        }
    }).get();
}

这里的wikiaddr是构造该文本对应的wiki页面的url地址,以后传给iframe。百度API以json格式返回数据,Request中会自动解析返回的json,所以这里翻译好的数据在response.json.trans_result[index].dst中。感觉worker是在往页面注入脚本时返回的一个类似该注入脚本的句柄一样的存在:

var worker = tab.attach({
    contentScriptFile: [data.url("jquery-1.11.2.min.js"), data.url("content.js")],
});

Add-on script和content script间传递消息

worker中的port对象用来向不同的标签页中注入的脚本content script传递消息,content script中同样使用port来接收和发送消息,分别是port.on()和port.emit()方法,content script中port为self对象一个内置属性。

Add-on script中发送消息,传递的消息可以是单独的文本或者json对象,下面传递一个数组:

worker.port.emit("get-transtext", [wikiaddr, transTxt+'</p>']);

content script中监听和接收消息:

self.port.on("get-transtext", function(textInfo) {
    //To do something
}

当页面中发生翻译请求时,content script会向Add-on script中发送一个名为text-selected的消息,用worker.on()监听这个消息并处理:

var worker = tab.attach({
    contentScriptFile: [data.url("jquery-1.11.2.min.js"), data.url("content.js")],
});
worker.port.on("text-selected", function(text) {
    getTransTxt(worker, text.toString());
});

在getTransTxt方法中对需要翻译的文本进行分析,用正则表达式判断是不是单词,是的话调用词典API进行词典解释,不是的话调用之前写的onBaiduTrans()方法翻译,所以这里还得写个请求词典API翻译的处理函数,具体可以看源码,注意下面url中yourAPIkey为百度开发者中心上申请的key

function getTransTxt(worker, text) {
    var transaddr = '';
    //词典API
    if ((text.search(/^\s?[a-zA-Z]{1,20}\s?$/i))>=0) {
        //去空格
        text = text.replace(/\s+/i,"");
        transaddr = "http://openapi.baidu.com/public/2.0/translate/dict/simple?client_id=yourAPIKey&q=";
        transaddr += encodeURIComponent(text) + "&from=en&to=" + translan;
        onBaiduDict(worker,text,transaddr);
    }
    else if ((text.search(/^\s?[\u4E00-\u9FA5]{1,4}\s?/))>=0) {
        text = text.replace(/\s+/i,"");
        onBaiduDict(worker,text,"http://openapi.baidu.com/public/2.0/translate/dict/simple?client_id=yourAPIKey&q=" + encodeURIComponent(text) + "&from=zh&to=" + translan);
    } else {
        //翻译API
        onBaiduTrans(worker,text,"http://openapi.baidu.com/public/2.0/bmt/translate?client_id=yourAPIKey&q=" + encodeURIComponent(text) + "&from=auto&to=" + translan);
    }
}

修改content script

添加翻译结果的面板

现在main.js文件里的代码功能已经基本完成,现在修改下之前写的需要注入到页面中的content.js,添加一个显示翻译结果的面板(div)到页面中,并添加与Add-on script收发信息的函数,完整修改后代码可查看源代码

下面是我添加一个面板的笨方法,用记事本写个面板的html,然后在Firefox里把该html的CSS修改好(在火狐里修改本地css真是非常方便),接着用jquery的.append()把html添加到页面,用.css()把CSS添加到页面:

//弹出翻译结果框
function showPanel() {
    $('body').append('<div id="content-div"><div id="top-div"><a href="javascript:void(0)" id="wiki-tab">WIKI</a><a href="javascript:void(0)" id="translator-tab">  TRANSLATOR</a></div><div id="frame-div" style=""><div id="trans-div" style="display:none;width:300px;height:auto;background:rgba(233, 233, 233, 1);opacity:.8;padding:10px;max-height:190px;overflow:auto;">blabla</div><iframe id="wikiframe" name="wikiframe" src="#" ></iframe></div></div>');
    $('#content-div').css({
        opacity: '0',
        display: 'none',
        width: '320px',
        position: 'fixed',
        right: '20px',
        bottom: '-190px',
        zIndex: '2147483647',
        font: 'bold 12px/25px Arial, sans-serif',
        background: 'transparent'
    });
    $('#top-div').css({
        height: '40px',
        width: '320px',
        background: 'rgba(0,0,0,.05)',
        borderRadius: '20px 20px 0px 0px',
        lineHeight: '40px',
        textAlign: 'center'
    });
    $('#wiki-tab').css({
        width: '160px',
        color: 'rgba(255, 255, 255, .88)',
        textDecoration: 'none',
        background: 'rgba(0,152,249,.6)',
        float: 'left',
        fontSize: '1em',
        borderRadius: '20px 20px 0px 0px'
    });
    $('#translator-tab').css({
        width: '160px',
        color: 'rgba(0, 0, 0, 0.25)',
        textDecoration: 'none',
        background: 'transparent',
        fontSize: '1em',
        float: 'left',
        borderRadius: '20px 20px 0px 0px'
    });
    $('#frame-div').css({
        boxShadow: '1px 1px 3px rgba(0, 0, 0, 0.33)',
        textAlign: 'left'
    });
    $('#wikiframe').css({
        width: '320px',
        height: '210px',
        opacity: '0.85',
        border: '0px'
    });

        //设置的state为表明当前tab的标识
    if (state == 2) {
        wikiTabToTrans();
    }
    //屏蔽content-div上的mouseup消息
    $('#content-div').mouseup(function() {
        return false
    });
    //点击事件,在翻译和维基两个tab间切换
    $('#wiki-tab').click(function() {
        if(state==2)
            transBtnToWiki();
        return false;
    });
    $('#translator-tab').click(function() {
        if(state==1)
            wikiTabToTrans();
        return false;
    });
}

接着是两个切换tab的函数:

//tab切换函数,同时对state状态设置
function transBtnToWiki() {
    state = 1;
    if(wikiurl!=''){
        $('#wikiframe').attr('src', wikiurl);
        wikiurl= '';
    }
    $('#translator-tab').css({
        color: 'rgba(0, 0, 0, 0.25)',
        background: 'transparent'
    });
    $('#wiki-tab').css({
        color: 'rgba(255, 255, 255, .88)',
        background: 'rgba(0,152,249,.6)'
    });
    $('#trans-div,#wikiframe').toggle();
}
function wikiTabToTrans() {
    state = 2;
    $('#wiki-tab').css({
        color: 'rgba(0, 0, 0, 0.25)',
        background: 'transparent'
    });
    $('#translator-tab').css({
        color: 'rgba(255, 255, 255, .88)',
        background: 'rgba(56, 189, 15, 0.6)'
    });
    $('#trans-div,#wikiframe').toggle();
}

与Add-on script间的消息传递

当翻译按钮被点击时,需要发送翻译选中文本的消息给Add-on script,同时监听Add-on script传过来的翻译结果,然后再显示结果在添加的翻译面板中

//绑定点击按钮事件,点击时向add-on script发送翻译文本消息
$('#my-add-btn').click(function(e) {
    $('#my-add-btn').css({
        display: 'none'
    });
    //向add-on script发送消息
    self.port.emit("text-selected", getSelecctTxt());
    $('#wikiframe').css('height', '0px');
    $('#add-loading-img').show();
    console.log("selecttext:" + getSelecctTxt());
    return false;
});

//监听add-ons script消息
self.port.on("get-transtext", function(textInfo) {
    if(state == 1){
        $('#wikiframe').attr('src', textInfo[0]);
        wikiurl = '';
    }else{
        wikiurl = textInfo[0];
    }
    isShow = true;
    $('#add-loading-img').hide();
    $('#content-div').show();
    $('#content-div').animate({bottom:'20px',opacity:'1.0'},800);
    $('#trans-div').html(textInfo[1]);
});

现在为止大部分的功能已经实现,接下来就要写一下本地化文件,和改一下pakeage.json的相关信息就差不多了,写了这么久终于可以收工了!

标签: firefox, 扩展插件, add-on, HTTP

已有 3 条评论

  1. Arrowing Arrowing

    博主,快翻很好用,赞一个!

    不过有点小问题啊,上QQ空间和Discuz论坛(其他很多网站也会,包括微软的、QQ邮箱)老是自动刷新和跳回首页,希望能早点修复,谢谢!

    1. littlejim littlejim

      谢谢反馈哟,自动刷新是因为有些网站有反frame嵌入的处理,等有时间再更新去掉iframe应该就好了呢 :)

添加新评论