Chrome已经位居现代浏览器榜首,其中一个重要原因就是插件丰富,开发一款自己的专属插件也比较容易入手。做一个跳转小温之家前后台和书签管理的页面。记录下大致的操作吧。
【wenqyChromeExt】这是当前扩展插件根目录,运行tree -f
命令查看目录结构。
Mainfest.json
看下Mainfest.json核心入口文件
{
“update_url”: “https://wenqy.com/crx”,
// 描述
“name”: “小温之家-行走在猿类世界”,
“description”: “小温之家-行走在猿类世界,记下你的世界,做自己最真实的友人!”,
“version”: “1.0.0”,
“permissions”: [
“*://*/*”,
“activeTab”,
“tabs”,
“contextMenus”, // 右键菜单
“webRequest”,
“webRequestBlocking”,
“storage”
],
// 图标
“icons”:
{
“16”: “imgs/map/icon16.png”,
“48”: “imgs/map/icon48.png”,
“128”: “imgs/map/icon128.png”
},
“background”: {
“page”: “background.html”
},
// 默认语言
“default_locale”: “zh_CN”,
// 引入脚本
“content_scripts”: [
{
// 匹配时使用脚本、样式
“matches”: [“https://*/*”, “http://*/*”],
“exclude_matches”: [],
“css” : [“css/wenqy.css”],
“js”: [“js/wenqy.js”],
// 运行 文档加载结束
“run_at”: “document_end”
}
],
“browser_action”: {
“default_title”: “点击进入小温之家”,
“default_icon”: “imgs/map/icon48.png”,
“default_popup”: “popup.html”
},
// 选项页
“options_page”: “options.html”,
// 默认策略限制
// “content_security_policy”: “script-src ‘self’; object-src ‘self'”,
//”web_accessible_resources”: [
// “imgs/map/*.png”
//],
“manifest_version”: 2
}
popup.html
popup.html 点击chrome浏览器插件图标后的弹出层,与用户交互界面。
<body id=“yc-baidu-translate”>
<div class=“container”>
<div class=“header”>
<div class=“jumbotron”>
<button class=“” id=“wenqy-page”><img title=“前往小温之家” src=“imgs/map/arrow_down_nomal.png” />登录小温之家</button>
</div>
</div>
<div class=“main”>
<div class=“select-l translate-from” data-click=“no-click”>
<div class=“selected-l”>
<span class=“selected-l-text” value=“”><img title=“前往小温之家” src=“imgs/map/right-arrow.png” />站点书签</span>
</div>
</div>
</div>
<div class=“row”>
<select id=“select_sites” style=“width:100%”>
<option value=“”>请搜索书签</option>
</select>
</div>
<div class=“yc-baidu-translate-footer”>
<div class=“icon_options”>
<a href=“javascript:;” id=“icon_options_home” class=“icon_options_item”>
<img title=“前往小温之家” id=“icon_options_home_img” src=“imgs/map/home.png”>
</a>
<a href=“javascript:;” id=“icon_options_setting” class=“icon_options_item”>
<img title=“插件设置” id=“icon_options_setting_img” src=“imgs/map/setup.png”>
</a>
<a href=“javascript:;” id=“icon_options_help” class=“icon_options_item”>
<img title=“帮助和反馈” id=“icon_options_help_img” src=“imgs/map/help.png”>
</a>
</div>
</div>
</div>
</body>
popup.js
popup.js popup.html引用的外部js文件,行为操作层
var haitao_sites = {
‘www.wenqy.com’: ‘小温之家’,
‘www.baidu.com’: ‘百度’
};
function parseURL(url) {
var domain;
if (url.indexOf(“/”) >= 0) {
domain = url.substr(0, url.indexOf(“/”));
} else {
domain = url;
}
var domainName, port;
var idx = domain.indexOf(“:”);
if (idx > 0) {
domainName = domain.substr(0, idx);
port = domain.substr(idx + 1);
} else {
domainName = domain;
}
var shortName = domainName.substr(url.indexOf(“.”) + 1);
if (shortName.indexOf(“.”) < 0) {
shortName = domainName;
}
var tmp2 = url.substr(url.indexOf(“/”) + 1);
var webContext = tmp2.substr(0, tmp2.indexOf(‘/’));
var uri = tmp2.substr(tmp2.indexOf(‘/’));
return {
domainName: domainName,
shortName: shortName,
port: port,
webContext: webContext,
uri: uri
}
}
function restore_options() {
chrome.storage.local.get(null, function(items) {
// console.log(‘items’, items);
if (items[‘custom_sites’] && items[‘custom_sites’].length > 0) {
var selectText = “”;
for (var i in items[‘custom_sites’]) {
var input_obj = parseURL(items[‘custom_sites’][i]);
var name = haitao_sites[input_obj.domainName] ? haitao_sites[input_obj.domainName] : input_obj.shortName;
selectText += ‘<option value=’+items[‘custom_sites’][i]+’>’+name+'<option>’;
}
$(“#select_sites”).empty().append(selectText);
}
})
}
restore_options();
$(document).ready(function() {
$(“#select_sites”).select2();
$(“#select_sites”).change(function(event) {
window.open(“http://” +$(“#select_sites option:selected”).val());
});
$(“#icon_options_setting”).click(function() {
window.open(‘options.html’);
});
$(“#icon_options_setting”).hover(function() {
$(“#icon_options_setting_img”).attr(‘src’, ‘imgs/map/setuphover.png’);
}, function() {
$(“#icon_options_setting_img”).attr(‘src’, ‘imgs/map/setup.png’);
});
$(‘#wenqy-page’).click(function() {
window.open(‘http://wenqy.com/wp-login.php’);
});
$(“#icon_options_home”).click(function() {
window.open(‘http://wenqy.com/’);
});
$(‘#icon_options_home’).hover(function () {
$(‘#icon_options_home_img’).attr(‘src’, ‘imgs/map/home_hover.png’);
}, function () {
$(‘#icon_options_home_img’).attr(‘src’, ‘imgs/map/home.png’);
});
$(‘#icon_options_help’).click(function () {
window.open(‘http://wenqy.com’);
});
$(‘#icon_options_help’).hover(function () {
$(‘#icon_options_help_img’).attr(‘src’, ‘imgs/map/help_hover.png’);
}, function () {
$(‘#icon_options_help_img’).attr(‘src’, ‘imgs/map/help.png’);
});
});
options.html
options.html 扩展插件的设置界面
<body>
<h1 style=“text-align:center;”>小温之家| 自定义设置</h1>
<h2>喜欢的颜色:</h2>
<h2 style=“text-align:center;” id=“status”></h2>
<br>
</br>
<div class=“autoTranslate”>
<div class=“autoTranslate-switch”>
<h2>喜欢的颜色:</h2>
<table id=“custom-head” class=“table”>
<tr>
<td id=“thead-tip”>
<select id=“color”>
<option value=“”></option>
<option value=“red”>red</option>
<option value=“green”>green</option>
<option value=“blue”>blue</option>
<option value=“yellow”>yellow</option>
<option value=“white”>white</option>
</select>
</td>
<td>
<a href=“#” id=“saveOptions”>保存</a>
</td>
</tr>
</table>
<h2>书签管理</h2>
<table id=“custom-head” class=“table”>
<tr>
<td id=“thead-tip”>
书签
</td>
<td>
<a href=“#” id=“add”>+添加站点</a>
</td>
</tr>
</table>
</div>
<div class=“table-container”>
<table id=“custom” class=“table-custom”>
</table>
</div>
</div>
</body>
wenqy.js
wenqy.js options.html 设置界面引用的外部行为操作层
function save_options() {
custom_sites = [];
$(‘.site’).each(function() {
if ($(this).text() != ” && custom_sites.indexOf($(this).text()) == -1) {
custom_sites.push($(this).text());
}
})
chrome.storage.local.set({
‘custom_sites’: custom_sites,
}, function() {
location.reload();
});
}
function restore_options() {
chrome.storage.local.get(null, function(items) {
// console.log(‘items’, items);
if (items[‘custom_sites’] && items[‘custom_sites’].length > 0) {
$(“#custom”).addClass(“table-custom-padding”);
for (var i in items[‘custom_sites’]) {
var input_obj = parseURL(items[‘custom_sites’][i]);
var name = haitao_sites[input_obj.domainName] ? haitao_sites[input_obj.domainName] : input_obj.shortName;
$(“#custom”).append(‘\
<tr>\
<td class=“site”><a href=“http://’ + items[‘custom_sites’][i] + ‘” target=“_blank”>’ + items[‘custom_sites’][i] + ‘</a></td>\
<td class=“site-name”>’ + name + ‘</td>\
<td class=“site-remove”><a href=“#” class=“remove”>移除</a></td>\
</tr>’);
$(“.remove”).click(function() {
$(this).parent().parent().remove();
save_options();
});
}
} else {
$(“#custom”).append(‘\
<tr id=“blank”>\
<td class=“custom-nothing”>无</td>\
</tr>’);
}
})
}
restore_options();
/**
* @author wenqy.com
*
*
*/
$(function(){
// Saves options to localStorage.
function save_options_test() {
var select = $(“#color option:selected”).val();
localStorage[“favorite_color”] = select;
// Update status to let user know options were saved.
$(“#status”).text(“选项已保存”);
console.log(“select->”+select);
$(“body”).css(“background-color”,select);
setTimeout(function() {
$(“#status”).text(“”);
}, 750);
}
// Restores select box state to saved value from localStorage.
function restore_options_test() {
var favorite = localStorage[“favorite_color”];
if (!favorite) {
return;
}
$(“#color”).val(favorite);
$(“body”).css(“background-color”,favorite);
}
restore_options_test();
$(“#saveOptions”).click(save_options_test);
var url_expression = /[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi;
var url_regex = new RegExp(url_expression);
var c_id = 0;
$(“#add”).on(‘click’, function() {
if ($(‘.add-tr’).length <= 0 ) {
if (!$(“#custom”).hasClass(“table-custom-padding”)) {
$(“#custom”).addClass(“table-custom-padding”);
}
$(“#custom”).before(‘\
<table id=“‘ + c_id + ‘” class=“add-table”>\
<tr class=“add-tr”>\
<td class=“td-add-input”>\
<input type=“text” class=“form-control site” placeholder=“请输入网站地址,如: www.wenqy.com” required>\
</td>\
<td class=“td-add-button”>\
<button type=“button” class=“switch-open add-confirm” style=“width:79px;float: none;margin-left:16px;”>添加</button>\
</td>\
<td class=“td-add-remove-button”>\
<button type=“button” class=“switch-close add-remove” style=“width:79px;float: none;”>取消</button>\
</td>\
</tr>\
<tr><td class=“fail”></td></tr>\
</table>’);
$(“.add-remove”).on(‘click’, function() {
$(this).parent().parent().parent().parent().remove();
if ($(“.site”).length <= 0) {
$(“#custom”).removeClass(“table-custom-padding”);
}
});
$(“#” + c_id + ” .add-confirm”).on(‘click’, function() {
var input_valid = true;
var url_input = $(this).parent().prev().children(‘input’).val().replace(‘。’, ‘.’).replace(‘http://’, ”).replace(‘https://’, ”);
if (url_input == “”) {
$(‘.fail’).text(‘输入内容不能为空’);
$(‘.fail’).show();
input_valid = false;
} else if (!url_input.match(url_regex)) {
$(‘.fail’).text(‘无效网址’);
$(‘.fail’).show();
input_valid = false;
}
if (input_valid) {
var input_obj = parseURL(url_input);
var name = haitao_sites[input_obj.domainName] ? haitao_sites[input_obj.domainName] : input_obj.shortName;
$(“#custom #blank”).remove();
$(“#custom”).prepend(‘\
<tr>\
<td class=“site”><a href=“http://’ + url_input + ‘” target=“_blank”>’ + url_input + ‘</a></td>\
<td class=“site-name”>’ + name + ‘</td>\
<td class=“site-remove”><a href=“#” class=“remove”>移除</a></td>\
</tr>’);
$(this).parent().parent().remove();
$(“.remove”).on(‘click’, function() {
$(this).parent().parent().remove();
save_options();
});
save_options();
}
});
c_id += 1;
}
});
});
直接将百度翻译的插件进行改造,阉割了。。。
该开始编写样例的时候报错,扩展页面动态绑定JS事件提示错误
Refused to execute inline event handler because it violates the following Content Security Policy directive: "script-src 'self' blob: filesystem: chrome-extension-resource:". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.
JavaScript事件都用外部引入的方式就可以了
Chrome插件安装
Chrome浏览器中输入URL:chrome://extensions
,进行【扩展程序】管理页面,当然也可以在【设置】里找,选择【加载已解压的扩展程序】,选中扩展插件的目录即可。当然也可以把扩展插件的目录打包,打包成.crx后缀结尾的扩展插件。
安装扩展后,如图所示:
点击【登录小温之家】,跳转到小温之家的后台登录界面;点击主页图标,跳转到小温之家首页,点击帮助图标也是;点击设置图标,跳转到站点管理页面。
添加站点后,就可以搜索选择啦,选择站点后,跳转到站点页面。
Console效果
var str = “WENQY”;
var mode = “stereo”; // 平面
if (mode === ‘planar’) {
var character = character_planar;
}
if (mode === ‘stereo’) { // 立体
var character = character_stereo;
}
var result = ‘\n’;
var strArr = str.split(‘\n’);
for (var k = 0; k < strArr.length; k++) {
for (var j = 0; j < 7; j++) {
for (var i = 0, length = strArr[k].length; i < length; i++) {
result = result + character[strArr[k][i]][j];
}
result = result + ‘\n’;
}
}
console.group(“Info”);
console.log(result);
console.log(“welcome to http://wenqy.com”);
console.log(” …..∵ ∴★.∴∵∴ ╭ ╯╭ ╯╭ ╯╭ ╯∴∵∴∵∴ “);
console.log(“.☆.∵∴∵.∴∵∴▍▍ ▍▍ ▍▍ ▍▍☆ ★∵∴ “);
console.log(“▍.∴∵∴∵.∴▅███████████☆ ★∵ “);
console.log(“◥█▅▅▅▅███▅█▅█▅█▅█▅█▅███◤ “);
console.log(“. ◥███████████████████◤ “);
console.log(“....◥████████████████■◤”);
console.log(“.. .. .. .. .. .. .. .”);
console.log(“.. .. .. .. . “);
console.log(“…友谊的巨轮向你驶来”);
console.groupEnd();
console.group(“Reference”);
console.log(“https://github.com/starkwang”);
console.log(“http://www.fuhaodq.com/fuhaotuan/1215.html”);
console.log(“http://www.cnblogs.com/tinyTea/p/6072618.html”);
console.log(“http://www.cnblogs.com/zhongxinWang/p/4121111.html”);
console.groupEnd();
);
效果图:
第一版自定义插件算是入门啦,当然存在痛点了,插件卸载后,重新安装并没有保存原先添加的站点记录,也没有为这些站点定义名称字段方便记忆和管理,话说还会再改吗?姑且记之吧。
参考
http://open.chrome.360.cn/extension_dev/overview.html
http://open.chrome.360.cn/extension_dev/manifest.html
本文由 wenqy 创作,采用 知识共享署名4.0
国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Nov 8,2020