仅保持一个firefox窗口 for firefox4 - 20101201更新
今天意外遭遇打开多个firefox窗口,正好趁机总结一下保持单个窗口的办法。
未完待续。。。
1. about:config
里面有几个设置参数跟新开窗口相关。
- browser. link. open_newwindow
对于网页上的超链,有一些通常是应该在新窗口打开的,比如设置了target=”_blank”,target=”new”,rel=”external”等等属性的链接。
通过这个参数可以定制上述链接在firefox中的打开方式。有3个可选值。1 : In the current tab or window 在当前tab或窗口打开
2 : In a new window 在新窗口打开
3 : In a new tab 在新tab里打开所以这里为了不在新窗口打开,我们应该配置成3或者1,根据自己的习惯选择。
其实菜单项Tools → Options → Tabs → Open new windows in a new tab instead
就是更改这个值,默认不勾选是2,勾选了是3。
- browser. link. open_newwindow. restriction
通过javascript打开的窗口(就是我们一般说的弹出窗口,比如广告那些)通过这个参数来控制。3个可选值。0 : 按照browser.link.open_newwindow参数的设置来处理.
1 : 弹出新窗口
2 : 如果JavaScript调用window.open()时设置了”features”参数则在新窗口打开,否则按照browser.link.open_newwindow参数的设置来处理这个设置成0。
- browser. link. open_external
这个参数在3.5时已经被删除,但是不排除以后还会恢复(现在bugzilla里面呼声很高)。
外部程序可能会通过firefox来加载页面,比如在email客户端里点了邮件中的一个链接。
这个参数就是用来控制如何打开外部程序传递进来的链接。3个可选值1 : Opens external links in current window 在当前窗口打开
2 : Opens external links in a new window 新窗口打开
3 : Opens external links in a new tab in the most recent window 在最上层窗口用新tab打开当前firefox4版本该参数无效,外部链接也是用browser.link.open_newwindow参数来控制,所以如果你想设置成网页里的链接在当前tab打开,而外部程序的链接在新tab打开,通过about:config已经实现不了了(需要其他扩展或脚本)。但是对于我们这个主题,browser.link.open_newwindow设置好就行。
2. UI上屏蔽在新窗口打开
用下面的CSS隐藏超链上右键菜单中“在新窗口打开”选项
#context-openlink {
display: none !important;
}
3. 脚本
脚本大体上分为2种。
- 第1种是从根本上禁止弹出新窗口 – 把所有打开新窗口的代码都替换成打开新tab或者在当前tab打开,比如shift+click超链就可以修改为在当前tab打开(原本是在新窗口)。这种办法需要hack浏览器的代码,修改也比较多(凡是涉及新开窗口的地方都要改),但是可以从最初始的地方杜绝新开窗口。
- 第2种办法是允许新开窗口,当侦测到有新的窗口打开时,再把它合并到先前开的窗口里,最后始终只保持一个窗口开着。这种办法实现起来比较简单,而且各种新开窗口的方式都能覆盖,但是在合并窗口之前会有一个时间段内是有多个窗口存在的。
思路清楚了,先来看看第2种简单的。代码基于quchao的singletonFox重写并简化了
(function() {
var singletonFox = null;
function isBlank(browser) {
return browser.mTabs.length===1 && browser.currentURI.spec==='about:blank' && browser.selectedBrowser.sessionHistory.count<2 && !browser.selectedTab.hasAttribute('busy') && !browser.selectedBrowser.contentDocument.body.hasChildNodes();
}
function isBusyLoading(browser) {
return browser.currentURI.spec == 'about:blank' && browser.selectedTab.getAttribute('busy') !== '' && !browser.selectedBrowser.contentDocument.body.hasChildNodes();
}
function check() {
var windowsEnumerator = Cc['@mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator).getEnumerator('navigator:browser');
if(windowsEnumerator.hasMoreElements()) {
// iterate all windows opened
while(windowsEnumerator.hasMoreElements()) {
var win = windowsEnumerator.getNext();
if(!singletonFox) {
singletonFox = win;
}
if(win !== singletonFox) {
var browser = win.getBrowser();
if(!isBlank(browser)) {
(function() {
if(isBusyLoading(browser)) {
setTimeout(arguments.callee, 0);
} else {
// merge session data
var sessionService =Cc['@mozilla.org/browser/sessionstore;1'].getService(Ci.nsISessionStore);
sessionService.setWindowState(singletonFox, sessionService.getWindowState(win), false);
singletonFox.focus();
win.BrowserTryToCloseWindow();
}
})();
} else {
win.BrowserTryToCloseWindow();
}
}
}
}
}
if(location == "chrome://browser/content/browser.xul") {
check();
}
})();
这个脚本只在新开窗口时执行一个check方法(43-45行),方法主体是遍历当前的所有已开窗口,并合并到一个窗口里。
02行的singletonFox变量保存唯一打开的窗口。
18-20行,如果singletonFox变量未初始化,则当前正在检查的窗口作为这个唯一的窗口。
21-38行,只要不是singletonFox对应的窗口,则关闭该窗口,把该窗口中的tabs合并到singletonFox窗口里去。
36行,如果这个窗口是一个空白窗口,直接关闭。
27-33行,通过sessionService来合并窗口。
25-27行,如果是一个新开的正在加载的窗口,使用定时器延时合并,这是为了避免由于合并导致加载停止。
isBlank和isBusyLoading是2个工具函数,分别用来判断是不是空白窗口和新开的加载窗口。
—————————————————————————————————–
第二种比较麻烦,首先得找出来哪些地方会打开新窗口,然后把代码修改成不要打开新窗口。
- shift+click网页链接
firefox4里面有个函数 – whereToOpenLink,从名字就能猜出来是用来决定链接在哪打开的。function whereToOpenLink(e, ignoreButton, ignoreAlt) { if (!e) { return "current"; } var shift = e.shiftKey; var ctrl = e.ctrlKey; var meta = e.metaKey; var alt = e.altKey && !ignoreAlt; var middle = !ignoreButton && e.button == 1; var middleUsesTabs = getBoolPref("browser.tabs.opentabfor.middleclick", true); if (ctrl || middle && middleUsesTabs) { return shift ? "tabshifted" : "tab"; } if (alt) { return "save"; } if (shift || middle && !middleUsesTabs) { return "window"; } return "current"; }看17-19行就知道,shift+click或者鼠标中建(需要开启browser.tabs.opentabfor.middleclick)会在新窗口打开链接。
所以,这里我们只需要把return “window”;替换掉就行。(function() { try { eval("whereToOpenLink = " + whereToOpenLink.toString().replace(/return "window";/g, 'return "tab";')); }catch(e) {} })();这样就实现了shift+click超链是在新tab而不是新窗口打开链接。
其实我更喜欢alt+click是当前tab打开,shift+click是save,改起来也很简单,可以自行尝试。
related post
- [uc]sideBookmarkBar for firefox4
- [userChrome script]flybar - 居中地址栏和搜索框 (扩展版 - flybar)
- pentadactyl试用记
- [KeySnail]编辑模式下使用可输入字符作为快捷键
- Tab Kit - tab相关的一些小脚本 for firefox4