在 chrome 商店上看到好多有意思的 chrome 插件,觉得非常的有意思,也有很多前端自己写了非常实用的扩展,非常的羡慕他们。通过这种扩展的方式,我们能实现很多单纯页面不好实现的功能。比如可以监控页面的 http 请求,方便的实现跨域等等。

扩展所需要用到的技术其实对于前端而言,门槛不高,就是我们开发中所用到的技术,所不同的是,我们在实现某些功能的时候可能需要 chrome 提供的 api。

可以通过 chrome 官方的 api 网站了解一个扩展所需要的一些 api, 如果不能翻的话,也可以访问国产浏览器的 翻译文档。这些网站介绍的都非常的详细,所以我就跳过如何如何新建文件等这样的步骤了。

首先要知道要实现什么功能,然后去寻找对应的 api。对于开发而言,经常需要去国外网站查找资料,或者每天都泡在 Github 上。这个时候英语不好的人,就会变得很尴尬,也许会遇到不会的单词,导致看不懂对应的上下文。频繁的去使用翻译网站,浪费时间。而且会显得很 low,哈哈。所以我打算实现一个简单的 划词翻译 的扩展。

在网页上选择了文本,会自动把这个文本发送到服务端,并且把翻译的结果显示在页面的右上角。比如下面这样:

现在开始第一个 Chrome 扩展吧

监听页面上获取选择文本的操作,很简单,直接使用 document.onselectionchangedocument.onselectstart 来监听页面上的用户行为。但是这个方法每选择一个文本,都会触发 onselect 事件。交互非常不好,所以我想到了使用 onmouseup 事件来判断当前用户是否选择了文本 window.getSelection()

既然能够获取页面上选择的文本,如何实现对文本的翻译那?

百度 API Store 给开发者提供了非常多的 api 可以调用,这其中有很多都是免费的。我们只需要将文本通过 AJAX 发送到 API 网站。如下图演示的功能:

现在开始第一个 Chrome 扩展吧

代码其实非常的简单:

/**
 * 实现网页内容翻译
*/ 
'use strict';

const achieveTranslationApi = {

  // 百度 API
  apikey: '319392ed1aa29475c579343e65d41266',

  // 查询的接口
  interface: document.location.protocol + '//apis.baidu.com/apistore/tranlateservice/translate',

  // AJAX 调用
  ajax: function( url, data ){
    // 缓存 this
    let _this = this, formated = url + this.encodedURIParams( data );
    // 返回一个 Promise
    return new Promise(function(resolve, reject){
      // 新增 HTTP 请求
      var http = new XMLHttpRequest();
      // 默认是 GET 提交
      http.open('GET', formated);
      // 配置参数
      http.setRequestHeader('apikey', _this.apikey);
      // 注册回调事件
      http.onreadystatechange = function(){
        // AJAX 响应解析完成
        if( this.readyState !== 4 ) return;
        // 输出回调
        this.status === 200 ? resolve( this.response ) : reject( this.statusText );
      };
      // 立即请求
      http.send( null );
    });
  },

  // 格式化参数
  encodedURIParams: function( params ){
    // 参数容器
    let formatedParamsArr = [];
    // 遍历对象
    for(let i in params) {
      // 开始填充
      formatedParamsArr.push(`${encodeURIComponent( i )}=${encodeURIComponent( params[ i ] )}`);
    }
    // 返回参数
    return '?' + formatedParamsArr.join("&");
  },

  // 执行查询功能
  excuteRequest: function(){
    // 等待查询的字段
    let requestData = {query: window.getSelection().toString(), from: 'en', to: 'zh'};
    // 阻止未选中事件
    if(requestData.query === undefined || requestData.query === '') return false;
    // 立即请求
    achieveTranslationApi.ajax(achieveTranslationApi.interface, requestData).then(function( data ){
      // 格式化参数
      let tempData = typeof data === 'string' ? JSON.parse( data ) : data;
      // 阻止错误事件
      if( tempData === null || tempData.errMsg !== 'success' ) return false;
      // 转化后的文本
      let translateWord = (tempData.retData.trans_result && tempData.retData.trans_result[0].dst) || 'Translation Error';
      // 实例化一个提示节点
      let tipsNode = document.createElement('div');
      // 移除已经存在的节点
      Array.from(document.getElementsByClassName('translation'), i => i && i.parentNode.removeChild( i ));
      // 添加转化后的文本
      tipsNode.innerText = translateWord.toString() || 'Empty Result';
      // 添加样式
      tipsNode.classList.add('translation');
      // 立即生成
      document.body.appendChild( tipsNode );
    });
  }
};


// 监听文档监听事件
document.onmouseup = achieveTranslationApi.excuteRequest;  

因为 google 上传扩展需要 5 美金的费用,还有就是申请上传感觉繁琐,所以就没有在官方上上传了。如果想获取这个扩展的话,可以点击 这里

功能其实非常简单,因为调用的是免费的 api,所以翻译的质量也不尽如人意。但是作为一个练手的项目还是不错的,在我以后的工作中也时常用到了这个扩展。以后会做更多有意思的功能。