剖析chrome扩大顺序-Holmes

前阵子在微博看到关于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构造:

<div id="link-wrap" class="cf">
    <a class="icon-question" href="http://www.blackfish.fi/holmes/" target="_blank" title="Holmes website"></a>
</div>

<section>
    <header class="cf">
        <div id="search">
            <img src="images/icon_19.png">
            <input id="pattern" type="text" autofocus="autofocus" autocomplete="off" placeholder="Holmes at your service.">
        </div>
    </header>
</section>

<section>
    <div id="view">
        <ol></ol>
    </div>
</section>

重要的节点是:输入框 #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, '<span>' + _inp_val_pat.exec(_string) + '</span>');
  };

  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 += "<li class=\"" + _classes + " cf\"><img src=\"chrome://favicon/" + mark.url + "\"><a href=\"" + mark.url + "\" title=\"" + mark.url + "\">" + _match + "</a></li>";
      }
      $view.html(_update);
      $current_mark = $view.children(':first');
      return $view.find('a').on('click', function() {
        return chrome.tabs.create({
          url: this.href
        });
      });
    } else {
      if (search != null) {
        $view.html('<div class="no-bookmarks-found"><h1>Oh no!</h1><p><b>No single bookmark found.</b><br>Press enter to Google!</p><p>Or you could check out<br><a href="http://www.blackfish.fi/holmes/" target="_blank" title="Holmes website">Holmes new website!</a></p></div>');
      }
      return $current_mark = null;
    }
  };

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年的事了,看来作者也没有继承更新的打算了)

    原文作者:Dont
    原文地址: https://segmentfault.com/a/1190000009889728
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞