10
13
2011
2

GM 脚本:在 Chito 后台评论列表中显示评论者的地址位置

GreaseMonkey 代码如下:

// ==UserScript==
// @name           is-programmer 后台评论地理位置显示
// @namespace      http://lilydjwg.is-programmer.com/
// @description    通过 JSONP 查询 IP 地址对应的地理位置并显示
// @include        http://*.is-programmer.com/admin/comments*
// @include        http://*.is-programmer.com/admin/messages*
// ==/UserScript==

var qurl = function(ips){
  return 'http://localhost:2000/queryip?q=' + ips.join(',') + '&cb=?';
};

var letsJQuery = function(){
  var ip_header = document.evaluate('//th[@class="helpHed" and text()="IP"]', document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null).snapshotItem(0);
  $(ip_header).after('<th class="helpHed">地址</th>');
  var ip_cells = document.getElementsByClassName('comment_ip_col');
  var ips = [];
  var i;
  for(i=0, len=ip_cells.length; i<len; i++){
    ips.push(ip_cells[i].textContent);
  }
  $.getJSON(qurl(ips), function(data){
    var ans = data.ans;
    for(i=0, len=ip_cells.length; i<len; i++){
      $(ip_cells[i]).after('<td class="comment_addr_col">'+ans[i]+'</td>');
    }
  });
};

function GM_wait(){
  if(typeof unsafeWindow.jQuery == 'undefined') {
    window.setTimeout(GM_wait, 500);
  }else{
    $ = unsafeWindow.jQuery;
    letsJQuery();
  }
}

GM_wait();

光有这个脚本是不够的,因为没有 IP 地址数据库。我不想像这样用 chrome 权限调用子进程之类的手段,而是从本地 HTTP server 取得数据,这样以后可以方便地扩展。HTTP server 使用 Python 的 tornado 框架写成,名字是“Web Service Provider”的缩写:

#!/usr/bin/env python3
# vim:fileencoding=utf-8

from subprocess import getoutput
from functools import lru_cache
import json

import tornado.web
import tornado.httpserver
from tornado.options import define, options

@lru_cache()
def lookupip(ip):
  return getoutput('cip ' + ip).replace('CZ88.NET', '').strip() or '-'

class IPHandler(tornado.web.RequestHandler):
  def get(self):
    q = self.get_argument('q').split(',')
    addr = []
    for ip in q:
      a = lookupip(ip)
      if 'illegal' in a:
        a = '(错误)'
      elif '\n' in a:
        a = ''
      addr.append(a)

    ans = {
      'ans': addr,
    }
    cb = self.get_argument('cb', None)
    if cb:
      self.set_header('Content-Type', 'text/plain; charset=utf-8')
      self.write('%s(%s)' % (cb, json.dumps(ans, ensure_ascii=False)))
    else:
      self.write(ans)

def main():
  define("port", default=2000, help="run on the given port", type=int)

  tornado.options.parse_command_line()
  application = tornado.web.Application([
    (r'/queryip$', IPHandler),
  ],
    debug=True,
  )
  application.listen(options.port)
  tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
  try:
    main()
  except KeyboardInterrupt:
    pass

用的是 Python 3.2,我很喜欢它的lru_cache装饰器。

10
7
2011
9

找回火狐的双击标签页组空白新建标签页功能

前两天更新到了火狐7,却发现双击标签页组的空白地方没有了反应。最开始以为是插件不兼容或者是bug,没想到搜索了下,却发现是个“feature”。

这个 bug 报告中,Mozilla 认为这样可以简化标签页组的操作。我是从这个帖子找到这个 bug 报告的。楼主The_Ben 说

I would be more than happy to see this being re-implemented in FF7, as I use it all the time, I find it to be the most convenient way to open a new tab in a tab group I have (and I'm not currently present at obviously, for that I have cmd+t).

看来不是我一个人喜欢这个功能。那么,让我把它找回来吧,就像找回状态栏、地址栏中的RSS按钮以及https://一样。

根据 bug 报告上的链接,我找到了这个补丁。看样子把这个补丁反着打上去就好。不过找到正确的文件却花了好长时间,还下载了共 1.2G 的火狐源代码来找寻,好在并不需要重新编译。

要修改的位置位于源代码中的groupitems.js文件中,它被tabview.js包含了,所以要修改的文件是这个tabview.js。到火狐的安装目录/usr/lib/firefox-7.0下没找到这个文件,只有omni.jar。这是个非标准的 zip 文件。使用unzip程序可正确解压,然后打上以下补丁:

diff -Nuar omni_orig/chrome/browser/content/browser/tabview.js omni/chrome/browser/content/browser/tabview.js
--- omni_orig/chrome/browser/content/browser/tabview.js	2010-01-01 00:00:00.000000000 +0800
+++ omni/chrome/browser/content/browser/tabview.js	2011-10-07 13:47:32.623127202 +0800
@@ -2304,6 +2304,10 @@
   this.keepProportional = false;
   this._frozenItemSizeData = {};
 
+  // Double click tracker
+  this._lastClick = 0;
+  this._lastClickPositions = null;
+
   // Variable: _activeTab
   // The <TabItem> for the groupItem's active tab.
   this._activeTab = null;
@@ -3871,6 +3875,28 @@
   _addHandlers: function GroupItem__addHandlers(container) {
     let self = this;
 
+    // Create new tab and zoom in on it after a double click
+    container.mousedown(function(e) {
+      if (!Utils.isLeftClick(e) || self.$titlebar[0] == e.target || 
+          self.$titlebar.contains(e.target)) {
+        self._lastClick = 0;
+        self._lastClickPositions = null;
+        return;
+      }
+      if (Date.now() - self._lastClick <= UI.DBLCLICK_INTERVAL &&
+          (self._lastClickPositions.x - UI.DBLCLICK_OFFSET) <= e.clientX &&
+          (self._lastClickPositions.x + UI.DBLCLICK_OFFSET) >= e.clientX &&
+          (self._lastClickPositions.y - UI.DBLCLICK_OFFSET) <= e.clientY &&
+          (self._lastClickPositions.y + UI.DBLCLICK_OFFSET) >= e.clientY) {
+        self.newTab();
+        self._lastClick = 0;
+        self._lastClickPositions = null;
+      } else {
+        self._lastClick = Date.now();
+        self._lastClickPositions = new Point(e.clientX, e.clientY);
+      }
+    });
+
     var dropIndex = false;
     var dropSpaceTimer = null;
patch -p1 < patch

然后把文件弄回原来的 jar 包里面。这里用到了源代码中的config/optimizejars.py文件把标准 zip 文件弄成原样。估计不弄也可以,只是效率会差一些。

7z a -tzip omni.jar
python2 ~/src/mozilla-release/config/optimizejars.py --optimize . . .
sudo mv omni.jar /usr/lib/firefox-7.0

然后重启火狐即可。只不过这样,以后火狐更新时又得重新弄一遍。

2011年11月9日更新:火狐 8 终于把这个特性加回来了。

2011年11月11日更新:火狐 8 还是不尽如人意,只是双击空白区域会新建标签页,双击标签页组时并不是这样。更新后的 patch 如下,同时去掉了新建组后将焦点置于组标题的行为:

diff -Nuar omni_orig/chrome/browser/content/browser/tabview.js omni/chrome/browser/content/browser/tabview.js
--- omni_orig/chrome/browser/content/browser/tabview.js	2010-01-01 00:00:00.000000000 +0800
+++ omni/chrome/browser/content/browser/tabview.js	2011-11-11 00:30:18.629851334 +0800
@@ -1290,7 +1290,7 @@
         drag.info.stop();
 
         if (!this.isAGroupItem && !this.parent) {
-          new GroupItem([drag.info.$el], {focusTitle: true});
+          new GroupItem([drag.info.$el]);
           gTabView.firstUseExperienced = true;
         }
 
@@ -2328,6 +2328,10 @@
   this.keepProportional = false;
   this._frozenItemSizeData = {};
 
+  // Double click tracker
+  this._lastClick = 0;
+  this._lastClickPositions = null;
+
   this._onChildClose = this._onChildClose.bind(this);
 
   // Variable: _activeTab
@@ -3901,41 +3905,26 @@
   // Helper routine for the constructor; adds various event handlers to the container.
   _addHandlers: function GroupItem__addHandlers(container) {
     let self = this;
-    let lastMouseDownTarget;
 
+    // Create new tab and zoom in on it after a double click
     container.mousedown(function(e) {
-      let target = e.target;
-      // only set the last mouse down target if it is a left click, not on the
-      // close button, not on the expand button, not on the title bar and its
-      // elements
-      if (Utils.isLeftClick(e) &&
-          self.$closeButton[0] != target &&
-          self.$titlebar[0] != target &&
-          self.$expander[0] != target &&
-          !self.$titlebar.contains(target) &&
-          !self.$appTabTray.contains(target)) {
-        lastMouseDownTarget = target;
-      } else {
-        lastMouseDownTarget = null;
+      if (!Utils.isLeftClick(e) || self.$titlebar[0] == e.target ||
+          self.$titlebar.contains(e.target)) {
+        self._lastClick = 0;
+        self._lastClickPositions = null;
+        return;
       }
-    });
-    container.mouseup(function(e) {
-      let same = (e.target == lastMouseDownTarget);
-      lastMouseDownTarget = null;
-
-      if (same && !self.isDragging) {
-        if (gBrowser.selectedTab.pinned &&
-            UI.getActiveTab() != self.getActiveTab() &&
-            self.getChildren().length > 0) {
-          UI.setActive(self, { dontSetActiveTabInGroup: true });
-          UI.goToTab(gBrowser.selectedTab);
-        } else {
-          let tabItem = self.getTopChild();
-          if (tabItem)
-            tabItem.zoomIn();
-          else
-            self.newTab();
-        }
+      if (Date.now() - self._lastClick <= UI.DBLCLICK_INTERVAL &&
+          (self._lastClickPositions.x - UI.DBLCLICK_OFFSET) <= e.clientX &&
+          (self._lastClickPositions.x + UI.DBLCLICK_OFFSET) >= e.clientX &&
+          (self._lastClickPositions.y - UI.DBLCLICK_OFFSET) <= e.clientY &&
+          (self._lastClickPositions.y + UI.DBLCLICK_OFFSET) >= e.clientY) {
+        self.newTab();
+        self._lastClick = 0;
+        self._lastClickPositions = null;
+      } else {
+        self._lastClick = Date.now();
+        self._lastClickPositions = new Point(e.clientX, e.clientY);
       }
     });
 
@@ -8967,7 +8956,7 @@
       let box = item.getBounds();
       if (box.width > minMinSize && box.height > minMinSize &&
          (box.width > minSize || box.height > minSize)) {
-        let opts = {bounds: item.getBounds(), focusTitle: true};
+        let opts = {bounds: item.getBounds()};
         let groupItem = new GroupItem([], opts);
         self.setActive(groupItem);
         phantom.remove();
      

2012年6月7日更新: 火狐13的代码更改了,添加了dblclick事件绑定函数,不需要自己追踪单击事件了。更新后的代码如下:

diff -Nuar omni_old/chrome/browser/content/browser/tabview.js omni/chrome/browser/content/browser/tabview.js
--- omni_old/chrome/browser/content/browser/tabview.js  2010-01-01 00:00:00.000000000 +0800
+++ omni/chrome/browser/content/browser/tabview.js  2012-06-07 16:49:49.174753472 +0800
@@ -1500,7 +1500,7 @@
         drag.info.stop();

         if (!this.isAGroupItem && !this.parent) {
-          new GroupItem([drag.info.$el], {focusTitle: true});
+          new GroupItem([drag.info.$el]);
           gTabView.firstUseExperienced = true;
         }

@@ -4142,40 +4142,8 @@
     let self = this;
     let lastMouseDownTarget;

-    container.mousedown(function(e) {
-      let target = e.target;
-      // only set the last mouse down target if it is a left click, not on the
-      // close button, not on the expand button, not on the title bar and its
-      // elements
-      if (Utils.isLeftClick(e) &&
-          self.$closeButton[0] != target &&
-          self.$titlebar[0] != target &&
-          self.$expander[0] != target &&
-          !self.$titlebar.contains(target) &&
-          !self.$appTabTray.contains(target)) {
-        lastMouseDownTarget = target;
-      } else {
-        lastMouseDownTarget = null;
-      }
-    });
-    container.mouseup(function(e) {
-      let same = (e.target == lastMouseDownTarget);
-      lastMouseDownTarget = null;
-
-      if (same && !self.isDragging) {
-        if (gBrowser.selectedTab.pinned &&
-            UI.getActiveTab() != self.getActiveTab() &&
-            self.getChildren().length > 0) {
-          UI.setActive(self, { dontSetActiveTabInGroup: true });
-          UI.goToTab(gBrowser.selectedTab);
-        } else {
-          let tabItem = self.getTopChild();
-          if (tabItem)
-            tabItem.zoomIn();
-          else
-            self.newTab();
-        }
-      }
+    container.dblclick(function(e) {
+        self.newTab();
     });

     let dropIndex = false;
@@ -9944,7 +9912,7 @@
       let box = item.getBounds();
       if (box.width > minMinSize && box.height > minMinSize &&
          (box.width > minSize || box.height > minSize)) {
-        let opts = {bounds: item.getBounds(), focusTitle: true};
+        let opts = {bounds: item.getBounds()};
         let groupItem = new GroupItem([], opts);
         self.setActive(groupItem);
         phantom.remove();

2012年7月29日更新: 火狐14又有新动作,见此文

Category: 火狐 | Tags: 火狐
9
29
2011
15

调教火狐地址栏

火狐 7 把链接开头的http://隐藏了。有些人觉得简洁我却觉得不爽。虽然已经确定完全复制时火狐像以前一样聪明,会连同http://一起复制,但是部分复制时就不好办了,比如我前边那个知乎的链接就去掉了 query 和 hash 部分。另外,有人说改 http 为 https 时不方便。我一直在用 Redirector 插件,倒不太在意这个。

那么,作为可定制性极高的一款浏览器,在火狐中如何把这个http://加回来呢?答案比想像的要简单很多:打开 about:config 页面,查找键名browser.urlbar.trimURLs,双击使其值从true变为false即可。(改 about:config 时不需要重启的哦~)

既然写成了博文,当然不止会说这一项设置啦。Vayn 提出地址栏文本双击时会全选,而不是像其它地方一样只选中一个单词。这个也困扰着我,但把双击改成拖选并不太难,所以以前没管。这次经过一些尝试性的搜索后,发现这个也在 about:config 里可以设定。至于全选整个URL嘛,三击就是了嘛。另外也有个选项设定首次单击时全选。

另外还有几个挺有用的选项,在此一并附上:

browser.ctrlTab.previews
Ctrl-Tab切换时预览(以前版本的为browser.allTabs.previews)。默认为false
browser.urlbar.trimURLs
是否显示链接中的http://(火狐7+)。默认为true
browser.urlbar.clickSelectsAll
单击地址栏时首先选中整个 URL。默认为false
browser.urlbar.doubleClickSelectsAll
双击地址栏时选中整个 URL。默认为true
browser.tabs.animate
新建或关闭标签页时是否使用动画。默认为true,禁用后速度可能会有较大提升
browser.tabs.insertRelatedAfterCurrent
是否在当前标签页的旁边(而不是最右边)打开标签页。默认为true
Category: 火狐 | Tags: 火狐
8
15
2011
14

userChrome 脚本:中键粘贴并搜索

Google 字典没了,但单词还是要查的。目前用的是沪江小D。实际上之前也一直在用它的划词查询书签。释义简单了点,但速度是足够快了。可是再也不能之前选中单词后点几下就能查到了(划词有时候会很烦,特别是与FireGuesture的搜索冲突的时候)。过了几天使用Ctrl-C来复制或者Ctrl-W来清除上一个词或者Ctrl-T打开新标签使用关键字搜索的日子,最终还是忍不住折腾了起来,最后终于写成以下脚本:

if(location == "chrome://browser/content/browser.xul"){
  var s = document.getElementById('searchbar');
  s.addEventListener('mousedown', function(e){
    if(e.button == 1){
      this.value = '';
    }
    return true;
  }, false);
  s.addEventListener('mouseup', function(e){
    if(e.button == 1){
      var where = e.altKey ? 'current' : 'tab';
    }
    setTimeout(function(){
      if(s.value){
        s.doSearch(s.value, where);
      }
    }, 100);
    return true;
  }, false);
}

使用方法:

先吐槽下:这使用方法可比脚本难找得多。我是边 Google 边摸索才弄明白的。

首先安装userChromeJS插件。火狐现在已经不再读取userChrome.js文件,所以需要这个插件。另外火狐5的话目前需要Add-on Compatibility Reporter这个插件。然后就是把代码粘贴到<firefox_profile>/chrome/userChrome.js文件里了。行家的话应该知道怎么单独文件之类的,我暂时就懒得研究了。

一切就绪后重启火狐。这时在搜索框点击鼠标中键就会将 X 剪贴板的内容粘贴到搜索框中并在新标签页中打开搜索。如果点击的时候按住Alt键的话,会在当时页面中打开。

最后,既然用到的 X 剪贴板,当然是不支持 Windows 了。(我还不会用Javascript操纵剪贴板。。。)

Category: 火狐 | Tags: 火狐 userChrome
7
26
2011
0

GM脚本:维基百科语言链接中,中英文优先

每次在一大堆语言列表中找“中文”或者“English”实在太累,所以想了这么个办法。虽然维基百科的页面已经使用了jQuery,但我还是执着地没有使用它。不过也用到了点新东西——XPath

// ==UserScript==
// @name           Wikipedia 语言链接顺序调整
// @description	   将维基百科中的中英文语言链接放到最前面
// @namespace      http://lilydjwg.is-programmer.com/
// @include        http://*.wikipedia.org/*
// @include        http://*.wiktionary.org/*
// @include        https://*.wikipedia.org/*
// @include        https://*.wiktionary.org/*
// ==/UserScript==

var links = document.evaluate('//*[@id="p-lang"]//a[text()="中文" or text()="English"]', document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
var ul;
for(var i=0, len=links.snapshotLength; i<len; i++){
  var link = links.snapshotItem(i);
  ul = ul || link.parentNode.parentNode;
  ul.insertBefore(link.parentNode, ul.firstChild);
}

我第一次、也是唯一一次看到在火狐中使用XPath的示例在这里这里是MDC文档。


点击安装。


2011年8月12日更新:加入了维基词典的支持。

2011年11月7日更新:加入对 HTTPS 的支持。

7
1
2011
10

GM 脚本:Google顶栏还是白色的好看

月光都说了,Google的大多数页面还是白色顶栏比较合适,黑的看着实在是不爽。所以还是改回来好了:

// ==UserScript==
// @name          White Google topbar
// @namespace     http://lilydjwg.is-programmer.com/
// @description	  bring back google's white topbar
// @include       http://*.google.com*
// @include       https://*.google.com*
// ==/UserScript==

var css = "#gbx3, #gbx4 { background-color: #ffffff; border-bottom: 1px solid #3366cc; } #gbz .gbzt, #gbz .gbgt, #gbg .gbgt, .gbts, .gbz0l { color: #3366cc !important; } .gbzt-hvr, .gbzt:focus, .gbgt-hvr, .gbgt:focus { background-color: #eff3fb; } .gbz0l .gbtb2 { border-top-color: #3d7af5 !important; } #gbi5 { background-position: -6px -22px; }";
if (typeof GM_addStyle != "undefined") {
  GM_addStyle(css);
} else if (typeof PRO_addStyle != "undefined") {
  PRO_addStyle(css);
} else if (typeof addStyle != "undefined") {
  addStyle(css);
} else {
  var heads = document.getElementsByTagName("head");
  if (heads.length > 0) {
    var node = document.createElement("style");
    node.type = "text/css";
    node.appendChild(document.createTextNode(css));
    heads[0].appendChild(node); 
  }
}

点击安装

Category: 火狐 | Tags: google GreaseMonkey
6
27
2011
14

令我失望的火狐,以及其它

火狐4正式版还没出来之前,我就很担心。一是因为好些扩展会用不了了,二是新的界面我不看好。现在已经到火狐5了。我觉得比3.6版本更好的地方却只有三点——速度更快、对标准的支持更好,以及标签页分组功能。

换火狐4,最主要的原因是换 Arch 了,源里面只有最新版。换到火狐5倒没什么。用户可见的改变可能只有标签栏和Chrome一样,在关闭后鼠标离开标签栏才会重新调整大小以方便连续关闭多个标签页。插件方面,装了个Add-on Compatibility Reporter,除了 Update Scanner 不能加新的页面外,尚未发现不能用的。

但是,看到这篇文章中写到火狐在Nightly7.0中去掉了地址栏的http://显示。即使复制URL时会加上,但这样使得把 http 改成 https 或者 ftp 都更麻烦了,而且,它从外观上破坏了 URI 的一致性。我想火狐是不会提供选项的,就像在前一篇文章里我说过火狐4的两个问题一样。只能靠插件了。

现在的火狐,一点点被Opera和Chrome同化,原有的我喜欢的特性一个个地需要依赖插件了。等到它和其它浏览器完全一样的时候,我不知道我还有什么理由去继续使用它了。插件?别提了,现在更新的速度太快,插件会一个接一个的不兼容,继续下去的话,最终连Chrome都不如。火狐已经没什么可期待的了。我现在只指望uzbl能够在我需要时取代火狐。

Ubuntu极力想推广自己,最后我离开了它。火狐在Chrome出现后推广的力度越来越强劲,看来我最终也只能离开它了。我注定是小众。不知道这是幸还是不幸。

To be popular or to be outstanding, it is a question.

2011年10月7日更新:关于地址栏的 URL,情况比预料的好一些,Mozilla 为其保留了一个选项。详见文章调教火狐地址栏

Category: 火狐 | Tags: 火狐
6
7
2011
0

GM 脚本:Ubuntu 中文论坛自动登录 & 展开代码

其实自动登录的部分很早就写了的,因为应用于同样的站点,所以就放一起了。

自动登录就不就了,据说是论坛一直就有的 bug。不过现在似乎好了,已经很少遇到需要重新登录的情况。代码展开嘛,是这样子的。Ubuntu 中文论坛支持使用[name]...[/name]的BBCode来调用 Geshi 插件进行语法高亮。不过高亮的代码却总是收缩起来,只能看到开头几行,要看完整的要么用滚动条,要么点击“展开”链接。Perl 的小骆驼书上有一句话我印象深刻:当程序超过一屏时,bugs 数量会突增。

// ==UserScript==
// @name           Ubuntu中文论坛自动登录
// @namespace      http://lilydjwg.is-programmer.com/
// @description    Ubuntu中文论坛自动登录
// @include        http://forum.ubuntu.com.cn/ucp.php?mode=login*
// @include        http://forum.ubuntu.com.cn/viewtopic.php*
// @include        http://forum.ubuntu.org.cn/ucp.php?mode=login*
// @include        http://forum.ubuntu.org.cn/viewtopic.php*
// ==/UserScript==

window.addEventListener("load", function(){
  setTimeout(function(){
    var links = document.querySelectorAll('a[onfocus]');
    if(links){
      var evt = document.createEvent("MouseEvents");
      evt.initMouseEvent("click", true, true, window,
			 0, 0, 0, 0, 0, false, false, false, false, 0, null);
      for(var i=0, len=links.length; i<len; i++){
        if(links[i].innerHTML == '展开'){
          links[i].dispatchEvent(evt);
        }
      }
    }
    if(document.querySelector('input[name=autologin]')){
      document.querySelector('input[name=autologin]').checked = true;
      document.querySelector('input[name=login]').click();
    }
  }, 1000);
}, false);

点击这里安装。可以到这个页面测试。

Category: 火狐 | Tags: GreaseMonkey javascript 火狐
4
16
2011
10

换火狐4了

既然决定换 Arch 了(虽然至今仍未换过去),终将放弃火狐3.6,于是终于地,我用上了火狐4。我的火狐4是从这里下载的国际版。一直很不喜欢中国版的火狐。

之所以没在第一时间使用火狐4,除了插件兼容性的担心外,我还很不喜欢火狐4的UI。标签栏和状态栏学Chrome、菜单学Opera就算了,打开附加组件栏后这算什么啊?下边明明有那么多的空间,状态栏非要浮在它上面!

对于自己的配置,我一向很保守,因此,我启动火狐4的命令是:

~/soft/firefox/firefox -P --no-remote

创建了一个新的 profile。我并没有把之前的 profile 复制过去,因为我觉得用了好几年的配置,是时候清理下了。

我先是尝试了下Pentadactyl这个vimperator的新分支,很快就放弃了,直接原因是,我没有找到能够用的使用拼音的 hint 插件。我可不想为了 follow 一个全中文的链接而伸手去按数字,不方便。根本原因还是不习惯 hint 这种方式,不想放弃自己已经养成的并没有任何明显问题的习惯。

于是再创建一个 profile,开始逐个安装自己要的插件。还好重要的插件都支持火狐4。弄完时安装了40个插件,一个炫彩风格。其中有一个插件是我不再留恋火狐3.6的重要原因——Status-4-Evar。我就知道喜欢火狐以前的状态栏的不止我一个,果然已经有了现成的插件。而且,这个插件还包含了Fission的功能——地址栏进度条,虽然填充的时候把地址栏的边框给遮住了。

最后,还有五个插件我想要,但是不支持火狐4:

  • Link Status,在状态栏显示链接是否已加为书签,以及如果访问过,上次访问的时间
  • FireRainbow,Firebug 的脚本高亮
  • CacheViewer,查看缓存文件的。除了从缓存中找媒体文件外,我还用它来删除因非正常关机等原因导致坏掉的缓存文件
  • History Submenus,将历史记录菜单按天分成子菜单
  • MR Tech Toolkit,增强附加组件管理页面,包括导出列表等

另外,还遭遇了一个bug:在安装若干插件后,打开附加组件管理页面,会停止响应,从 strace 的信息来看是死锁了。不过既然是新版,只出了一个bug还是比较好理解的。想当初,刚转到Linux下的时候,那个火狐各种崩溃……至于配置插件,对于没有在附加组件栏之类的地方提供打开“选项”对话框的插件,只好看它的源码然后像这样访问啰:

chrome://imagetweak/content/prefs.xul
chrome://textlink/content/pref/prefDialog.xul

火狐4新增的标签页分组功能很好用,可以把与当前工作不相关的网页放到另外的组,以免像Chrome那样让标签页挤满标签栏,所以Tree Style Tab也不需要了。而且,当一个分组里的标签页太多而分组占用的区域很小的时候,火狐也处理得很好。注意到截图下方中央有个按钮,点一下就会弹出一个大的区域,展示被“叠放”在一起的标签以便操作。在分组管理界面中也支持中键关闭、双击新建,那些功能很明显的按钮我就不说了。不过我在想,如果它支持Awesome或者Subtle那样的平铺,再加上多个工作区(或者边界不局限于窗口边界),那样就更好了。

最后要说一下的是,火狐原先位于地址栏的RSS订阅按钮没了,说是用的人少,不想让它占地方(Orz....)。办法有二,要么点“书签”按钮,然后在下拉菜单里找,要么定制工具栏,拖个RSS图标到工具栏上,并不能放到地址栏里。而且这样的话,即使网页没有提供RSS功能,RSS图标依旧显示,这才是真正的占用宝贵的空间呢!


2011年4月29日更新:

今天火狐提示尽快升级到 4.0.1。升级之后,附加组件管理页面终于恢复正常了!

Category: 火狐 | Tags: 火狐
11
6
2010
2

privoxy与火狐智能地址栏两者兼得

privoxy是一款强大的代理调度器,看到muzuiget同学的介绍我就心动了,由于比较忙所以前两天才开始尝试,很快就发现了一个问题:直接在火狐地址栏里输入关键字会转到privoxy的“找不到域名”的错误页。

依我的推测,火狐总是尝试解析用户在地址栏输入的字符串,当解析失败时就尝试添加.com这样的后缀,然后尝试向Google查询,或者返回一个最接近的结果,或者返回Google搜索页面。(所以,我非常讨厌垃圾电信的114广告,使得任何原本不能解析的域名都解析到它的广告页了。)

在使用HTTP代理之后,火狐无法得知域名解析是否成功,因为代理在出错时返回了出错页面。这让我这个重试依赖她的地址栏的火狐迷郁闷了一天,最终(部分地)解决了此问题。

privoxy果然强大,出错页都是可以自定义的,默认这些模板在配置目录的templates目录下,很容易猜到处理域名解析失败的文件是no-such-domain。于是我在改了下其外观的同时,先是加上搜索功能:

<p>
    This is often a temporary failure, so you might just
    <a href="@protocol@@hostport@@path@">try again</a>,
    or <a href="https://encrypted.google.com/search?hl=zh-CN&q=@hostport@">Google @host@</a>.
</p>

这样还不行,不光得点一下,而且只能跳转到Google的搜索页。想到Google有个“手气不错”按钮,于是利用之:

var abar = function(){
  if(document.referrer) return;
  var host = "@host@";
  if(host.indexOf('.')<0 || host.indexOf(' ')>-1){
    document.title = "跳转中...";
    window.location = "https://encrypted.google.com/search?hl=zh-CN&q="+host+"&btnI=1";
  }
};
abar();

将这段代码加到<head>后即可实现输入关键字后自动使用Google的“手气不错”服务跳转到接近的页面,或者是Google搜索页面。

但测试几次后发现,这样还有问题:如果输入中文,将搜索其punycode而不是中文了。比如在地址栏输入“测试”,回车之后会搜索“xn--0zwm56d”,进而跳转到http://www.iana.org/domains/root/db/xn--0zwm56d.html。看来需要用Javascript解punycode了。Google下,在stackoverflow看到了一个实现,还是放弃版权的~只是我没发现怎么才能让privoxy的错误页调用本地的外部Javascript文件,所以直接把代码嵌进去了,这让我这个喜欢代码整洁的人有点不爽。。。

var abar = function(){
  if(document.referrer) return;
  var host = punycode.ToUnicode("@host@");
  if(host.indexOf('.')<0 || host.indexOf(' ')>-1){
    document.title = "跳转中...";
    window.location = "https://encrypted.google.com/search?hl=zh-CN&q="+host+"&btnI=1";
  }
};
abar();

按说这样的设计是跨浏览器的,于是我测试了下Google Chrome,发现其并不买帐,输入看起来不像域名的字符串后,Chrome直接进到搜索页面。。。。还是火狐好啊~~

Category: 火狐 | Tags: javascript 火狐 privoxy

| Theme: Aeros 2.0 by TheBuckmaker.com