Google Chrome 扩展 - CodeProject 声誉监视器
Google Chrome 扩展,可抓取您的声望积分和图表,并跟踪更新之间的变化。
- Chrome 网上应用店 - 由于新的 Google 政策要求,安装通过 Chrome 网上应用店提供。
- 下载源代码 V2.0 - 228.8 KB
V2 重要更改
由于 Google 为保护用户免受恶意代码侵害而实施的政策变更,该扩展需要进行多项更改。
- 将 manifest 更新为新的 V2 标准。
- 从 Chrome 网上应用店分发扩展。
- 从 HTML 页面中删除内联脚本块。
我还利用这些更改升级了新的 jQuery 文件,并重构了部分其他代码。
引言
本文是为了尝试一些新主题而撰写的。为了尝试这些新主题,最好尝试开发一个功能性组件,而不是仅仅玩弄代码语法。
本文将探讨如何构建一个 Google Chrome 扩展,以及我如何利用 jQuery 和 jQuery UI 来构建该扩展。那么这个扩展会做什么呢?该扩展可以获取用户 CodeProject 个人资料页面的来源,并抓取他们的声望积分。该扩展将这些积分存储在本地,并比较与 Code Project 之间的轮询变化,然后将这些信息呈现到一个漂亮的小表格中。该扩展还可以获取成员的声望图表并在扩展中显示。
背景
构建此扩展所需的信息可以在 Google Chrome 扩展的页面上找到。有关 jQuery 和 jQuery UI 的信息,请参见此处和此处。
Chrome 扩展
Chrome 扩展实际上是一系列包含完全嵌入的 JavaScript 和 CSS 的 HTML 文件,或者可以链接到其他 JavaScript、CSS 和图像文件。为了让 Chrome 知道如何处理所有这些文件以及如何将其呈现给用户,项目根目录中的 manifest 文件定义了各种元素。manifest 文件必须命名为 'manifest.json'。
让我们来看看为这个扩展制作的 manifest 文件
{
"manifest_version": 2,
"name": "CodeProject Reputation Watcher",
"short_name": "CPRepWatcher",
"version": "2.0",
"content_security_policy": "script-src 'self' https://# 'unsafe-eval'; object-src 'self' ",
"description": "Extension to retrieve a CodeProject accounts reputation points.",
"icons": {
"48":"images/bob48.png",
"128":"images/bob128.png"
},
"browser_action": {
"default_icon": "images/bob.png",
"default_popup": "cprepwatch.html"
},
"options_page": "options.html",
"permissions": [
"http://*.codeproject.com/"
]
}
有一些基本属性,如 'name
'、'version
' 和 'description
',这些都是不言而喻的。'icons
' 元素定义了扩展可用的图像;这些图像会显示在安装后的 Chrome 扩展页面上。
'browser_action
' 元素告诉 Chrome 在工具栏中显示哪个图标,以及哪个 HTML 文件是扩展图标被点击时的主要弹出窗口。
'options_page
' 元素告诉 Chrome 将显示哪个 HTML 页面,允许用户设置扩展使用的任何选项/用户设置。此页面可以通过右键点击工具栏按钮显示的选项菜单访问,或者从 Chrome 的工具菜单访问的 Chrome 扩展页面上的选项链接访问。
'permissions
' 元素定义了扩展想要访问的站点,并用于跨站点安全模型。
(Manifest 版本 1) 'update_url
' 元素定义了自动更新工具用于检查扩展新版本修订版的 XML 文件。从 V2 开始,由于扩展托管在 Chrome 商店中,因此不再需要此项。Chrome 浏览器负责版本更新过程。此属性随后被删除。
您还可以看到新规则要求的 'manifest_versions'
和 'content_security_policy'
更改。我还注意到,上传到 chrome 商店的人不喜欢 manifest 中有注释行,因此也必须删除这些注释。这只是通过反复试验才发现的,因为错误消息并没有提供太多帮助。
根据您的需求,还可以向 manifest 文件添加其他一些元素;这些元素的详细信息可以在 Chrome 扩展开发者页面上找到。
添加 jQuery 和 jQuery UI
要使用这些 JavaScript 库,您需要先从开发者站点下载它们,在此处和此处。在 jQuery UI 站点上,还有许多预定义的样式可用于 UI 元素,您还可以使用网站的样式生成器创建自己的样式。下载包含库和样式的 zip 文件后,解压缩这些文件并将它们添加到您的项目文件夹中。每个想要使用这些库的页面都必须在 HTML 中链接它们。这很容易通过标准标记来实现。
<link type="text/css"
href="css/custom-theme/jquery-ui-1.8.2.custom.css" rel="Stylesheet" />
<script type="text/javascript" src="jquery/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="jquery/jquery-ui-1.8.2.custom.min.js"></script>
<script type="text/javascript" src="js/cpjshelper.js"></script>
您还会注意到有一个指向 'js/cpjshelper.js' JavaScript 文件的引用。随着扩展的开发,常见的共享辅助函数被移到了这个文件中,以最大化代码重用并使 HTML 文件更整洁。
为什么使用 jQuery?
jQuery 提供了一种出色的操作和遍历 DOM 的方法。一旦我掌握了它的语法,它就使事情变得非常容易,这只需要很短的时间。以下是一些基本示例,说明它可以做什么
//Insert some HTML into a Div element named 'holdingdata'
$("#holdingdata").html("the html markup would go here");
$("#anElement").hide(); //Hide an element
$("#anElement").show(); //Show an element
$("p").each(function(){ $(this).hide();});
//Find all 'p' tags and hide them
下面的 jQuery 命令在浏览器文档加载完成后执行一个函数。该函数设置一个计时器,在一段时间后调用另一个函数。.get()
执行一个 HTTP GET 的 AJAX 查询,然后将返回的数据传递给另一个函数进行处理。AJAX 调用可以是同步或异步的,取决于您的需求。这两个辅助函数是用于处理 CodeProject 地址和数据的 JavaScript 函数。
$(document).ready(function () {
setTimeout(function () {
//Start loading the data from Codeproject profile
$.get(getCPMemberProfile(), function (data) {
setCPProfileData(data);
});
}, 1000);
});
这仅仅是 jQuery 全部功能的冰山一角,如果您访问开发者站点并浏览文档,您很快就会明白我的意思。
为什么使用 jQuery UI?
jQuery UI 提供了一套全面的界面小部件,可以插入到您的 HTML 中,然后使用 CSS 标记,提供一套丰富的界面组件。在此扩展中,使用的组件是 Tabs 面板和一个基本按钮。
Tabs 面板的创建非常简单,如下所示
<script type="text/javascript">
$(function() {
$("#tabs").tabs();
});
</script>
<div id="tabs" style="height: 400px;">
<!-- Tab Pages -->
<ul>
<li><a href="#tabs-1">Reputation Points</a></li>
<li><a href="repgraph.html">Reputation Graph</a></li>
<li><a href="#tabs-3">Options</a></li>
<li><a href="about.html">About</a></li>
</ul>
<!-- Tab 1 Rep Points -->
<div id="tabs-1" style="padding-left: 5px">
<!-- Main Rep Page content -->
</div>
<!-- Tab 2 Rep Graph ; Note: This does not require a section
as it is a link URL in tab definition above. -->
<!-- Tab 3 Options -->
<div id="tabs-3" style="padding-left: 5px">
<!-- Options Tab Content goes Here -->
</div>
<!-- Tab 4 About ; Note: This does not require a section
as it is a link URL in tab definition above. -->
</div>
您还会注意到 Tab 2 (Rep Graph) 和 Tab 4 (About) 是对扩展文件内外部文档的引用。这些内容通过 AJAX 加载,然后注入到当前页面的 DOM 的相应标签位置。
抓取 CodeProject 内容
为了检索 CodeProject 内容,一个 JavaScript 函数首先使用 AJAX 调用加载成员个人资料页面。返回的内容然后被放置在页面上的一个隐藏的 Div
块中,然后可以使用 jQuery 访问、遍历和解析该块。CodeProject 内容中有三个主要的 Element
用于标识要抓取的区域。它们是 'ctl00_MC_Prof_TotalRepBox
' 用于总体成员级别,'ctl00_MC_Prof_TotalRep
' 用于总声望积分,以及 'ctl00_MC_Prof_Status
' 用于所有类别的单个积分。
//The Total Reputation Member Level is Found in
if ($("#ctl00_MC_Prof_TotalRepBox").hasClass("nostatus")) { $("#repStatus0").html(" "); };
if ($("#ctl00_MC_Prof_TotalRepBox").hasClass("bronze")) { $("#repStatus0").html("Bronze"); };
if ($("#ctl00_MC_Prof_TotalRepBox").hasClass("silver")) { $("#repStatus0").html("Silver"); };
if ($("#ctl00_MC_Prof_TotalRepBox").hasClass("gold")) { $("#repStatus0").html("Gold"); };
if ($("#ctl00_MC_Prof_TotalRepBox").hasClass("platinum"))
{ $("#repStatus0").html("Platinum"); };
//The Total Reputation is found in this node
var thestring = $("#ctl00_MC_Prof_TotalRep");
if (thestring) { newRep[0] = thestring.text(); } else { newRep[0] = "0"; }
$("#loadRepTotal").html(newRep[0]);
//Reputation Points table
holdingdata.innerHTML = $('table.member-rep-list').html();
一旦内容被找到并复制到 holding Div
中,jQuery 就被用来提取内部元素中的文本。下面是用于定位每个 TableRow
,然后在其中找到每个 TableData
并定位 Points
、Category
和 Status
级别,然后将它们注入 DOM 以便呈现给用户的代码。
$("#holdingdata").find("tr").each(function (iTR) {
$(this).find("td").each(function (iTD) {
var MemberLevel = "";
if ($(this).hasClass("nostatus")) { MemberLevel = "" };
if ($(this).hasClass("bronze")) { MemberLevel = "Bronze" };
if ($(this).hasClass("silver")) { MemberLevel = "Silver" };
if ($(this).hasClass("gold")) { MemberLevel = "Gold" };
if ($(this).hasClass("platinum")) { MemberLevel = "Platinum" };
//Version 1.6 21st March 2011, Additional second link in each category
//iterate all the links determining a Category/Value pair
var thevalue = $(this).find("div.medium-text").text();
if (!thevalue) { thevalue = "";
$(this).find("a").each( function (iA) {
var category = $(this).text();
var category = $(this).find("a").text();
if (!category) { category = "No Data"; };
category = category.toUpperCase(category);
switch (category) {
case ("AUTHOR"):
newRep[1] = thevalue;
$("#loadRepAuthor").html(newRep[1]);
$("#repStatus1").html(MemberLevel);
break;
case ("AUTHORITY"):
newRep[2] = thevalue;
$("#loadRepAuthority").html(newRep[2]);
$("#repStatus2").html(MemberLevel);
break;
// Other case statements
for the other categories continue...........
}
});
});
});
测试代码
为了测试代码,首先将未打包的扩展加载到 Chrome 中。要做到这一点,选择 '工具',然后是 '扩展' 菜单,展开开发者面板,然后选择 '加载未打包的扩展...',然后导航到包含扩展所有文件的文件夹。扩展将被加载,显示为未打包,并且 manifest 中指定的图标等应该出现在工具栏和扩展的左侧。
要查看幕后情况,您可以右键点击工具栏并选择 '检查弹出窗口',查找错误,查看本地存储中存储了什么等等。在修改代码库/HTML 文件时,只需点击扩展中的 '重新加载' 即可更新。
为了辅助测试,您可以在扩展中放置一些 JavaScript 代码输出到 Chrome 调试器;这很简单,就像
//Output the contents of a variable to the debugger
console.log(variablename);
//Output a string to the debugger
console.log("Some text.");
本地存储数据/设置
对象可以本地存储,在此扩展中,存储了 CodeProject 成员 ID 以及上一次数据轮询的声望积分。持久化数据很容易,正如您下面所见,在需要时也很容易召回数据。
// Put data in the local store
var sometext = "Hello";
localStorage["AnyKeyName"] = sometext;
// Get data from the local store
var sometext;
sometext = localStorage["AnyKeyName"];
// Test the data does exist and was read
if (!sometext)
{
// The data is not present in the local store
}
打包和部署/托管
扩展有两种分发方法
- 未打包方法,虽然有效,但主要适用于测试和开发场景。
- 通过 Chrome 网上应用店进行 Google 托管。
未打包的扩展可以从此文章下载,该扩展也已发布到 Chrome 网上应用店。
已不再允许打包的扩展。这些将被浏览器阻止并禁用。
有关打包、部署和 Google 托管的更多信息,请参阅扩展打包。
如何使用此扩展?
您可以下载并安装未打包的扩展,或者点击上面的链接从网上应用店安装。
注意: 在“工具 | 扩展”菜单中安装未打包的扩展(以开发者模式)将允许您从源代码安装。但是,浏览器会不断提醒您并询问您是否要禁用此模式。
通过以上任何一种方法安装后,您只需从选项菜单项、扩展选项链接,或从实际扩展的选项卡中,将其设置为您的 CodeProject 成员 ID。您的成员 ID 可以在您的帐户的个人资料页面上找到。
每次点击扩展工具栏按钮时,它将显示文章顶部的页面,并用您最新的积分更新表格。
扩展上的其他标签如下:声望图、选项和关于。
扩展卸载
安装扩展后,只需点击卸载链接并删除解压缩未打包扩展的源文件夹即可。
下一步
代码库可能不是最优化的,所以需要整理一下,但和往常一样,一旦它能工作,我就不愿意改变任何东西。如果我有时间,我可能会研究一下,并可能添加一些其他功能,比如自动刷新。
跟踪使用情况和用户交互
可以通过将 Google Analytics 代码添加到文件中来跟踪扩展的使用情况。通过此,您可以跟踪正在查看的页面、被点击的按钮等。有关 Analytics 集成的更多信息可以在此处找到。
关注点
由于这是我第一次接触 Chrome 扩展、jQuery 和 jQuery UI,这无疑是一项挑战,但也非常有益。
已知问题
Chrome 中似乎有一个奇怪的缓存相关问题,这只有在您输入无效的 CodeProject 成员 ID 时才会出现:例如,导航到您的成员个人资料,然后导航到一个无效的个人资料,导航到另一个人的个人资料,再导航到同一个无效的个人资料,您会看到您最初输入的成员个人资料显示出来……我无法解释这一点,而且对于扩展的正常使用来说,这并不重要。只要您使用有效的成员 ID:一切都会正常。
历史
(版本号与代码更改相关,而不是文章修订版。)
- V2.0 2014 年 6 月 18 日 - 更新至新的 Chrome 要求,jQuery 更新至 V1.11.1
- 2013 年 10 月 23 日 - 由于 Chrome 更改,更新安装说明
- V1.6, 2011 年 3 月 21 日 - 为 CodeProject DOM/成员个人资料更改而更新
- V1.5, 2010 年 12 月 13 日 - 为 CodeProject DOM 更改而更新
- V1.4, 2010 年 10 月 20 日 - 添加了总体成员级别
- V1.3, 2010 年 9 月 10 日 - 解决了一些 Google Analytics 问题
- V1.2, 2010 年 9 月 9 日 - 修复了一些 JS 错误,将“关于”内容移至独立文件并通过 AJAX 调用,添加了 Google Analytics 跟踪。还在文章中介绍了到私有 Web 服务器的打包和部署详细信息
- V1.1, 2010 年 8 月 4 日 - 修复以处理新的成员状态 CSS 类 ID;从 zip 文件中删除了冗余的 CSS 主题
- V1.0, 2010 年 8 月 1 日 - 文章的第一个版本