7
29
2012
1

Revert new site identity feature and show favicon in urlbar for Firefox 14 & 15

(中文文章请见此处。)

If a user can be cheated by a site icon, the user can still be cheated even  when you remove that icon.

For the patch for Firefox 14, click here; for the omni.ja file, check this. This includes the long-lost feature that double-clicking on the space in a tab group will open a new tab.

For Firefox 15 patch.The omni.ja file is at the same location.

For Firefox 16 patch.The omni.ja file is at the same location.

Category: 火狐 | Tags: 火狐
7
29
2012
18

调教火狐14&15:地址栏显示网页图标,以及总结

好吧,我确认 Mozilla 已经脑残了,各种我喜欢的特性正在被去除,而我不喜欢的特性正在从 Google Chrome 抄袭过来。

火狐14开始,不再在地址栏显示网站图标了。Mozilla 说这样更安全,可我觉得,对于网站弄个挂锁图标就可以骗过的用户,地址栏图标去掉了他们依然会中招。而标签栏上的图标,我只用来识别标签页。地址栏图标的优势在于,不管标签页在哪里,它的位置总是固定的,用户不需要去判断当前标签页在哪里。于是我费了好久,终于通过查询火狐的源码库把这个特性加回来了。要补丁的请点击此处,我也提供打包好的 omni.ja 文件GFW认证。其中包含了自火狐7以来失去的双击标签页组创建新标签页的修改。

另外,火狐14地址栏默认自动填充到域名。可是我要域名干什么呢——我要访问的是页面!谁没事老去看人家网站的首页啊,当 RSS 不存在似的……好在我们还有个选项:browser.urlbar.autoFill。把它设置成false就可以了。


接下来,让我们怀念一下那些已经不再默认或者已经去除的特性(链接为找回该特性的办法)——

2012年8月30日更新:针对火狐15的补丁omni.ja文件地址不变。

2012年10月16日更新:针对火狐16的补丁omni.ja文件地址不变。

2013年4月16日更新:针对火狐20的补丁以及omni.ja文件地址在上述 Wuala 网盘地址中。

2013年11月27日更新:对于火狐 21 及以后,参见这里通过 userChrome 脚本的实现。

Category: 火狐 | Tags: 火狐
6
17
2012
13

彻底关闭火狐13新建标签页的缩略图导航

我一直在反对新版火狐某些特性。火狐13在新建标签页时添加了和 Opera、Google Chrome 一样的缩略图导航,这个对我一点用处也没有,因此也得干掉。

我并不满足于单纯地点击右上角那个小图标,因为这样之后,在打开新标签页时,我还是能看到 Status-4-Evar 显示于地址栏的进度条一闪而过。虽然加载新标签页的速度依然远快于 IE8,但是我不会轻易满足的。打开 about:config 页面,搜索「newtab」,我找到了这么一项:

browser.newtab.url,默认值是about:newtab。果断将其改成about:blank,恢复之前的空白页。

2012年6月27日更新:根据这篇文章,如果要禁止火狐在后台生成缩略图,还需要将选项browser.newtabpage.enabled置为false。(感谢巴蛮子指出。)

Category: 火狐 | Tags: 火狐
3
3
2012
6

GM 脚本:github 默认下载格式改为 gzip

不知道为什么,新版 github 在项目首页上只提供 zip 归档格式的下载,要下载 gzip 包还需要点击 download 到新页面去。可是我就是不喜欢 zip 格式嘛——

// ==UserScript==
// @name           github 下载默认 gzip 格式
// @namespace      http://lilydjwg.is-programmer.com/ 
// @description    把默认的 zip 下载按键改成 gzip 的
// @include        https://github.com/*
// ==/UserScript==
 
var dl = document.querySelector('.btn-download');
if(dl){
  dl.title = dl.title.replace('zip', 'gzip')
  dl.href = dl.href.replace('/zipball/', '/tarball/');
  var icon = dl.querySelector('.icon');
  if(icon){
    icon.nextSibling.textContent = 'GZIP';
  }
}
Category: 火狐 | Tags: GreaseMonkey 火狐 linux github
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 的支持。

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: 火狐

| Theme: Aeros 2.0 by TheBuckmaker.com