前言
笔者之前一直想了解一些关于谷歌插件的相关知识,希望通过谷歌插件可以更好的认识到谷歌的调试工具,同时也想着可以使用谷歌插件去写一些小工具,既学习了新的东西,又有一定的趣味性。恰逢近段时间需要分享,因此花了两周时间学习和了解谷歌插件相关知识,本篇文章就将笔者在学习过程中的一些思考分享给大家。当然,因为时间的原因,如果笔者对于这一块的认识有不对的地方,欢迎批评指正~
什么是谷歌插件
谷歌插件,全名谷歌浏览器扩展程序,官方说明如下:
扩展程序允许您为 Chrome 浏览器增加功能,而不需要深入研究本机代码。您可以使用您在网页开发中已经很熟悉的核心技术(HTML、CSS 与 JavaScript)为 Chrome 浏览器创建新的扩展程序。
有同学可能会疑惑:为什么又叫做谷歌插件?那这就正如鲁迅所说的那句话:世上本没有路,走的人多了,也就有路了。谷歌浏览器扩展程序本来并不是谷歌插件,谷歌插件其实是浏览器更为底层的东西,奈何叫的人太多了,谷歌浏览器扩展程序也就成了“谷歌插件”。本文也使用谷歌插件来统称谷歌浏览器扩展程序。
谷歌插件的基本使用
下面先介绍一下谷歌插件的主要组成部分,因为目前谷歌插件使用比较普遍的版本为 2.0 版本,因此本文都是基于 2.0 版本进行使用说明,3.0 版本相较于 2.0 版本更为简便,感兴趣的同学可以点击文章末尾处的链接了解更多相关知识。
谷歌插件的核心文件就是配置文件--manifest.json(清单)文件。
其中,manifest.json 文件最基本的 Api 如下:
{
"name": "chrome extension",
"version": "1.0.0",
"manifest_version": 2,
"description": "A litlle chrome extension demo"
}
主要是包含所写谷歌插件的名称、版本以及相关描述,其中 manifest_version 表示清单文件版本。
manifest.json 作为谷歌插件的核心部分,笔者认为该文件对插件来说就相当于一个入口配置文件,开发人员只需要在这个文件通过配置相应的 js,调用谷歌浏览器提供的 Api,就能实现达到完善这个插件的目的。
在清单文件中有 许多的Api,笔者就不一一列举了,下面为大家介绍几个笔者认为比较重要的 Api,通过以下几个 Api 的介绍,希望可以使读者对于谷歌插件的开发过程有一个大概的认识。
1)browser_action
{
...
"browser_action": {
"default_icon": {
"16": "images/get_started16.png",
"32": "images/get_started32.png"
},
"default_title": "谷歌划词翻译",
"default_popup": "popup.html"
},
...
}
2)permissions
{
...
"permissions": [ "activeTab", "storage", "tabs", "contextMenus" ],
...
}
{
...
"content_scripts": {
"matches": ["<all_urls>"],
"css": ["content/content_script.css"],
"js": ["content/content_script.js"]
},
...
}
4)background
{
···
"background": {
"scripts": ["background.js"],
"persistent": false
},
···
}
谷歌划词翻译插件
<div class="translate-panel show">
<header>谷歌划词翻译插件<span class="close">X</span></header>
<main>
<div class="source">
<div class="title">英文</div>
<div class="content">test</div>
</div>
<div class="result">
<div class="title">简体中文</div>
<div class="content">...</div>
</div>
</main>
</div>
// manifest.json
{
...
"content_scripts": {
"matches": ["<all_urls>"],
"css": ["content_script.css"],
"js": ["content_script.js"]
},
"permissions": [
"activeTab"
],
...
}
// content_script.js
class TranslatePanel {
createPanel = () => {
let wrapper = document.createElement('div')
wrapper.innerHTML = `
<header>谷歌划词翻译插件<span class="close">X</span></header>
<main>
<div class="source">
<div class="title">英文</div>
<div class="content">test</div>
</div>
<div class="result">
<div class="title">简体中文</div>
<div class="content">...</div>
</div>
</main>
`
wrapper.classList.add('translate-panel')
wrapper.querySelector('.close').onclick = () => {
this.wrapper.classList.remove('show')
}
document.body.appendChild(wrapper)
this.wrapper = wrapper
}
showPanel = () => {
this.wrapper.classList.add('show')
}
translateSelect = (content) => {
const source = this.wrapper.querySelector('.source .content')
const result = this.wrapper.querySelector('.result .content')
source.innerHTML = content
result.innerHTML = '翻译中...'
fetch(`https://translate.google.cn/translate_a/single?client=at&sl=en&tl=zh-CN&dt=t&q=${content}`)
.then(res => res.json())
.then(res => {
result.innerHTML = res[0][0][0]
})
}
locationPanel = (target) => {
this.wrapper.style.top = target.y + 'px'
this.wrapper.style.left = target.x + 'px'
}
}
let panel = new TranslatePanel()
panel.createPanel()
window.onmouseup = (target) => {
// 获取选中内容
const content = window.getSelection().toString().trim()
if (!content) return
panel.locationPanel({ x: target.pageX, y: target.pageY })
panel.translateSelect(content)
panel.showPanel()
}
<div class="switch-wrapper">
<div class="switch-desc">是否启用划词翻译</div>
<input type="checkbox" class="switch" />
</div>
// popup.js
let switchWrapp = document.querySelector('.switch')
chrome.storage.sync.get(['checked'], (target) => {
if (target) {
switchWrapp.checked = target.checked
}
})
switchWrapp.onclick = (e) => {
chrome.storage.sync.set({ checked: e.target.checked })
chrome.tabs.query( {active: true, currentWindow: true }, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, { checked: e.target.checked })
})
}
// content_script.js
let checked = false
window.onmouseup = (target) => {
···
if (!content || !checked) return
···
}
chrome.storage.sync.get(['checked'], (target) => {
if (target) checked = target.checked
})
chrome.runtime.onMessage.addListener((target) => {
if (target) {
checked = target.checked
}
})
// content_script.js
let panel = new TranslatePanel()
panel.createPanel()
window.onmouseup = (target) => {
// 获取选中内容
const content = window.getSelection().toString().trim()
if (!content) return
window.chrome.storage.sync.get(['checked'], (result) => {
if (result.checked) {
panel.locationPanel({ x: target.pageX, y: target.pageY })
panel.translateSelect(content)
panel.showPanel()
}
})
}
chrome.runtime.onMessage.addListener((target) => {
if (target.type == 'CHECKED') {
chrome.storage.sync.set({ checked: target.checked })
}
})
// backgrond.js
// 当扩展程序第一次安装、更新至新版本或 Chrome 浏览器更新至新版本时产生
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
"id": "SELECT_TRANSLATE",
"title": "翻译 %s",
"contexts": ["selection"]
})
})
chrome.contextMenus.onClicked.addListener((target) => {
if (target.menuItemId == 'SELECT_TRANSLATE') {
chrome.tabs.create({url: `https://translate.google.cn/?sl=en&tl=zh-CN&text=${target.selectionText}&op=translate`})
}
})
// content_script.js
translateSelect = (content) => {
const source = this.wrapper.querySelector('.source .content')
const result = this.wrapper.querySelector('.result .content')
source.innerHTML = content
result.innerHTML = '翻译中...'
chrome.runtime.sendMessage({ type: 'QUERY_TRANSLATE', queryContent: content }, (res) => {
result.innerHTML = res[0][0][0]
})
}
// background.js
chrome.runtime.onMessage.addListener((request, sender, callBack) => {
if (request.type == 'QUERY_TRANSLATE') {
fetch(`https://translate.google.cn/translate_a/single?client=at&sl=en&tl=zh-CN&dt=t&q=${request.queryContent}`)
.then(res => res.json())
.then(res => {
callBack(res)
})
return true
}
})
结尾
袋鼠云在大数据领域深耕7年,拥有丰富的大数据平台建设经验和成熟的产品体系,想了解或咨询更多有关袋鼠云大数据产品、行业解决方案、客户案例的朋友,浏览袋鼠云官网:https://www.dtstack.com/?src=bbs
同时,欢迎对大数据开源项目有兴趣的同学加入「袋鼠云开源框架钉钉技术群」,交流最新开源技术信息,群号码:30537511,项目地址:https://github.com/DTStack