摘要:業務邏輯業務邏輯在內,主要涉及的是按鍵事件交互處理以及檢索結果展示。目前,這個擴展程序在說明上貌似最新一版已經是年的事了,看來作者也沒有繼續更新的打算了
前陣子在微博看到關于chrome書簽搜索的擴展程序Holmes,于是使用了一下,確實還不錯,尤其書簽多很多的情況下,有個搜索功能 ,比定時做書簽分類等等方便得多很多。看著擴展程序功能簡單,感覺實現應該不難,于是我就試著查看一下擴展程序源碼,也可以順便進一步了解chrome擴展程序的實現方法和操作api。
本篇文章意在講解Holmes的主要實現,對于chrome擴展程序怎么一步一步建立起來,就不做重復說明,網上搜索即可。
首先,既然要研究擴展程序源碼,那么最直接的方式當然就是從chrome安裝目錄來尋址該擴展程序的所在目錄了。
這點,其實網上有資料可以查看的,比如這里>>
步驟1,在chrome地址欄輸入:chrome://version 回車,將結果頁中“個人資料路徑”一欄對應的值復制(其實是一個目錄路徑)
步驟2,打開資源管理器,鍵入剛復制的路徑,進入目錄,打開Extsions目錄,里面都是各種以字母組合的命名文件夾,對應的其實是各個擴展程序,命名其實是擴展程序的id
步驟3,在地址欄輸入:chrome://extensions,進入擴展程序管理頁,找到對應的擴展程序選項,有ID,對應的ID值就是對應的擴展程序文件夾名字。這似乎是個唯一值,holmes的ID是:gokficnebmomagijbakglkcmhdbchbhn
遵循上面三個步驟,我們就可以找到Holmes的擴展程序目錄了 ,將其復制到方便查看的位置,就可以開始查看源碼了。
理解配置做過擴展程序的都知道,項目必須有一個配置文件manifest.json
這里列一下主要的配置字段,不全
{ "background": { "page": "watson.html" }, "browser_action": { "default_icon": "images/icon_19.png", "default_popup": "holmes.html", "default_title": "Holmes" }, "commands": { "_execute_browser_action": { "suggested_key": { "default": "Alt+Shift+H" } } }, "description": "Chrome Bookmark Search Extension", "icons": { "128": "images/icon_128.png", "16": "images/icon_19.png", "48": "images/icon_48.png" }, "manifest_version": 2, "minimum_chrome_version": "25", "name": "Holmes", "omnibox": { "keyword": "*" }, "permissions": [ "bookmarks", "tabs", "chrome://favicon/" ], "update_url": "https://clients2.google.com/service/update2/crx", "version": "3.2.1" }
可以看到,這里有個permissions字段,字面意義應該是跟權限相關,這里配置了bookmarks、tabs、和chrome://favicon/,這為后面要用到chrome的一些功能埋下了伏筆(這么說好么?= =)
另外browse_action字段定義了點擊擴展程序圖標的一些行為,default_popup規定了點擊彈出框定位到holmes.html,也就是擴展程序的業務頁面,即搜索框和搜索結果。
深入頁面找到holmes.html,查看頁面會發現,頁面主要引入的js文件:
jquery 庫文件 fuse.min.js 模糊查詢工具 jquery.Core.js 基于jquery的核心方法 keymaster.min.js 按鍵事件工具 jquery.holmes.js 基于jquery的頁面業務邏輯
頁面的主要dom結構:
主要的節點是:輸入框 #pattern 和 搜索結果 #view.
到此,我們大概了解了holmes主要用到的是jquery來方便編程,利用keymaster來處理按鍵事件,利用fuse的模糊搜索來實現模糊查詢書簽。
那么,我們怎么獲得chrome的書簽呢?如果書簽有增刪改,又該怎么辦呢?另外,我要怎么打開標簽頁來承載某個書簽呢?
獲取書簽和標簽頁操作獲取書簽,其實就呼應了前面說過的配置權限permissions.
我們怎么知道的? 首先定位到jquery.Core.js文件,文件內容很簡單,不過做了壓縮,這里我優化了一下方便走讀。
(function() { var o, r; window.Holmes = { bookmarks: [], version: 3.21, showShortcutInfo: !1 }; r = function(o) { return function(o) { var e, t, n, a; for (a = [], t = 0, n = o.length; n > t; t++) { e = o[t]; if(e.hasOwnProperty("children")){ a.push(r(e.children)); }else{ if(e.url.match(/^javascript/)){ a.push(void 0); }else{ (e.title || (e.title = e.url), a.push(Holmes.bookmarks.push({ title: e.title, url: e.url }))); } } } return a } }(this); o = function() { return chrome.bookmarks.getTree(function(o) { return Holmes.bookmarks = [], r(o) }) }; chrome.bookmarks.onCreated.addListener(function(r, e) { return o() }); chrome.bookmarks.onRemoved.addListener(function(r, e) { return o() }); chrome.bookmarks.onChanged.addListener(function(r, e) { return o() }); Holmes.getPlaceholder = function() { var o; return o = ["Holmes at your service.", "How can I help you?", "It is a good day for searching.", "You know my methods. Apply them."], o[Math.floor(Math.random() * o.length)] }; o() }).call(this);
這里主要是定義了全局對象:Holmes,包含三個屬性,其中最主要的是bookmarks,它是一個數組,存儲chrome上的書簽,怎么存的呢?
在上述代碼上可以看出,通過調用chrome.bookmarks.getTree, chrome.bookmarks是chrome提供的書簽對象api,用于各種書簽操作,chrome書簽操作>>, 這里getTree就是獲取書簽樹結構,參數為回調函數,從回調函數參數可以獲得樹節點,通過children可以獲得子節點,于是這里是實現對節點的處理 ,當有children節點時,遞歸操作,無則當做鏈接獲取title跟url屬性,并push到bookmarks數組去(有可能收藏的是腳本代碼,這塊這里做了過濾處理)。
要用chrome.bookmarks,從官方文檔可知道, 需要配置permissions權限
{ "name": "My extension", ... "permissions": [ "bookmarks" ], ... }
另外,bookmarks對象還有事件處理函數,這里用于更新書簽數據以備檢索。
chrome.bookmarks.onCreated.addListener chrome.bookmarks.onChangeed.addListener chrome.bookmarks.onRemoved.addListener
這里還沒涉及到tabs,但因為都要配置permissions,所以提前說明,同樣,tabs也有官網文檔說明
其配置權限類似bookmarks,關于tabs的使用相當簡單:
chrome.tabs.create({url:xxx, pinned:true}) // 打開標簽頁,url為鏈接, pinned是否固定標簽頁
標簽頁這里主要是打開標簽頁,那就只需要用到這條api,其他可以到上面文檔說明去查看。
業務邏輯業務邏輯在holmes.js內,主要涉及的是按鍵事件交互處理以及檢索結果展示。
對于檢索結果,其實是從全局對象Holmes.bookmarks入手, 對其采用fuse模糊搜索。
fuse的具體操作可以看 fuse官網
使用很簡單,如下:
// 配置對象,檢索關鍵屬性 var option = { keys:["id"] }; // data為測試數據 f = new Fuse(data, options); f.search("查找內容"); //這里將對data的id屬性做 查找內容 的搜索
在holmes里,使用很簡單:在輸入框監聽keyup,清空結果dom($view), 對書簽數據進行模糊查詢(鍵值:書簽標題),得到結果調用updateView方法來給$view更新內容。(涉及到鍵入監聽,其實還可以考慮做節流操作避免重復執行搜索)
代碼如下:
// 監聽輸入框keyup事件 $("#pattern").on("keyup", function(e) { var _kc, _ret, f, options; _kc = e.keyCode; if (_kc === 38 || _kc === 40 || _kc === 37 || _kc === 39) { $(this).css("-webkit-user-select", "text"); return false; } pattern = $("#pattern").val(); // 清空搜索結果 $view.html(""); _ret = []; if (pattern.length > 0) { pattern.replace(" ", ""); options = { keys: ["title"] }; // 對title進行查詢 f = new Fuse(Holmes.bookmarks, options); _ret = f.search(pattern); } else { _ret = []; search = null; } // 調用updateView對搜索結果進行展示 return updateView(_ret); });
關于updateView: 已經設定了bmarks_per_page變量用來定義結果顯示數量(并非把全部書簽結果都輸出,而是輸出前十條數據),并且對標題進行省略裁剪,并針對關鍵字插入span標簽(可做樣式高亮,但擴展程序并沒有做),在拼接dom模板時對首條數據加入current類,并且將對應的dom保存到$current_mark,用于回車時直接打開以及顯示選中項,對拼接的dom添加到$view中,并且定義a標簽點擊事件(由于每次搜索結果都是重新添加內容,所以這里不會涉及重復綁定,但其實可以給$view做事件代理更佳)
代碼如下:
matchString = function(_string, _char_count) {
var _inp_val_pat;
_string = _string.length < _char_count ? _string : _string.substr(0, _char_count) + "...";
_inp_val_pat = new RegExp(pattern, "gi");
return _string.replace(_inp_val_pat, "" + _inp_val_pat.exec(_string) + "");
};
updateView = function(bmarks) {
var _classes, _match, _update, i, j, len, mark;
if (bmarks.length > 0) {
_update = "";
for (i = j = 0, len = bmarks.length; j < len; i = ++j) {
mark = bmarks[i];
// 我認為這里直接break跳出循環即可,無需continue繼續循環
if (!(i < bmarks_per_page)) {
continue;
}
_classes = i === 0 ? "current" : "";
_match = matchString(mark.title, 50);
_update += "
ps:這里有個小知識點,其實也涉及到permissions配置,在chrome下,chrome://favicon/+頁面地址 可以獲得該網站的favicon.
其他按鍵交互:除了輸入框鍵入字符的監聽外,還監聽了回車打開標簽頁和切換結果選中項,主要用了keymaster
其api可以參考這里:keymaster官網
主要的代碼:
key.filter = function(event) { var tagName; tagName = (event.target || event.srcElement).tagName; return !(tagName === "SELECT" || tagName === "TEXTAREA"); }; key("down, up", function(e, h) { if (($current_mark != null) && $view.children().length > 1) { switch (h.shortcut) { case "down": if ($current_mark.index() !== bmarks_per_page - 1 && $current_mark.index() < $view.children().length - 1) { return $current_mark = $current_mark.removeClass("current") .next("li") .addClass("current"); } break; case "up": if ($current_mark.index() !== 0) { return $current_mark = $current_mark.removeClass("current") .prev("li") .addClass("current"); } } } }); key("enter, shift + enter", function(e, h) { switch (h.shortcut) { case "enter": case "shift+enter": if ($current_mark != null) { return chrome.tabs.create({ url: $current_mark.find("a").prop("href"), pinned: key.shift ? true : false }); } else { if (pattern.length > 2) { return chrome.tabs.create({ url: "http://www.google.com/search?q=" + pattern }); } } } });
至此,holmes的主要邏輯也就解讀完畢了, 對于樣式那塊,本文不做解讀,可看出,其實該擴展程序,還有很多優化空間,感興趣,其實可以自己改改,來優化使用體驗,比如:代碼的一些重復邏輯、加入事件代理、搜索結果顯示體驗等等。(目前,這個擴展程序在說明上貌似最新一版已經是2015年的事了,看來作者也沒有繼續更新的打算了)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/83591.html
摘要:作為一名資深碼農,結合身邊一群民工的真實體驗,小編有那么一點權威給各位推薦幾款程序員必備常用的擴展插件。插件是一款為谷歌瀏覽器定制的非常強大的一款管理插件。 作為一名資深碼農,結合身邊一群IT民工的真實體驗,小編有那么一點權威給各位推薦幾款程序員必備、常用的chrome擴展插件。1.Click&Clean下載地址:http://www.cnplugins.com/offi...Clic...
摘要:前端日報精選大前端公共知識梳理這些知識你都掌握了嗎以及在項目中的實踐深入貫徹閉包思想,全面理解閉包形成過程重溫核心概念和基本用法前端學習筆記自定義元素教程阮一峰的網絡日志中文譯回調是什么鬼掘金譯年,一個開發者的好習慣知乎專 2017-06-23 前端日報 精選 大前端公共知識梳理:這些知識你都掌握了嗎?Immutable.js 以及在 react+redux 項目中的實踐深入貫徹閉包思...
摘要:通過團隊的全力全策,美團外賣的平均率從千分之三降到了萬分之二,最優值萬一左右率統計方式次數。美團外賣自年創建以來,業務就以指數級的速度發展。目前美團外賣日完成訂單量已突破萬,成為美團點評最重要的業務之一。 面試中常常問到的是Android的性能優化以及Crash處理。 今天我們來學習一下啊美團App的Crash處理。更多參考《Android性能優化:手把手帶你全面實現內存優化》 原為地...
閱讀 2949·2021-11-23 09:51
閱讀 1666·2021-10-15 09:39
閱讀 1056·2021-08-03 14:03
閱讀 2880·2019-08-30 15:53
閱讀 3437·2019-08-30 15:52
閱讀 2487·2019-08-29 16:17
閱讀 2788·2019-08-29 16:12
閱讀 1647·2019-08-29 15:26