Skip to content

Instantly share code, notes, and snippets.

@knoajp
Created August 9, 2017 08:39
Show Gist options
  • Save knoajp/c93c2747a7145f1cb822393a71789271 to your computer and use it in GitHub Desktop.
Save knoajp/c93c2747a7145f1cb822393a71789271 to your computer and use it in GitHub Desktop.
CloseTabLater
/* タブを閉じる(CloseTabLater) */
(function(){
const DELAY = 5*1000;
const OPACITY = '0.5';
let current = gBrowser.mCurrentTab;
/* 最後のタブだったら素直に閉じる */
if(gBrowser.mTabContainer.childElementCount === 1) return gBrowser.removeTab(current);
/* 現在のタブに閉じる運命を与える */
let label = 'CloseTabLater-' + Date.now() + DELAY;
if(!('CloseTabLaters' in window)) window.CloseTabLaters = [];
window.CloseTabLaters.unshift(label);
current.CloseTabLater = true;
current.classList.add(label);
current.style.opacity = OPACITY;
current.addEventListener('TabSelect', function(e){
if(current.hasAttribute('muted')) current.toggleMuteAudio();
window.CloseTabLaters.splice(window.CloseTabLaters.indexOf(label), 1);
delete current.CloseTabLater;
current.classList.remove(label);
current.style.opacity = '';
clearTimeout(timer);
});
current.addEventListener('TabClose', function(e){
window.CloseTabLaters.splice(window.CloseTabLaters.indexOf(label), 1);
delete current.CloseTabLater;
current.classList.remove(label);
clearTimeout(timer);
});
let timer = setTimeout(function(){
gBrowser.removeTab(current);
}, DELAY);
/* 音をミュートに(個別メディア要素の停止はiframe探索も必要でしんどい) */
current.addEventListener('DOMAttrModified', function mute(e){
if(current.selected) return current.removeEventListener('DOMAttrModified', mute);
if(current.soundPlaying && !current.muted) return current.toggleMuteAudio();/*新規の音発生を防止*/
});
/* 次に選択されるタブは getFirstChildTab, getNextSiblingTab, getPreviousSiblingTab, getParentTab の優先順 */
let nextTab = function(tab){
let dir = nextTab.dir = ('dir' in nextTab) ? nextTab.dir : 1;
if('TreeStyleTabService' in window){
let tree = TreeStyleTabService, noChild = nextTab.noChild = ('noChild' in nextTab) ? nextTab.noChild : {};
if(tree.getParentTab(tab)) nextTab.noChild[tree.getParentTab(tab)._tPos] = true;
if(dir === 1){
if((noChild[tab._tPos] || !tree.getFirstChildTab(tab)) && !tree.getNextSiblingTab(tab) && tree.getPreviousSiblingTab(tab)) nextTab.dir = -1;
return (noChild[tab._tPos] ? null : tree.getFirstChildTab(tab)) || tree.getNextSiblingTab(tab) || tree.getPreviousSiblingTab(tab) || tree.getParentTab(tab);
}else{
if((!noChild[tab._tPos] && tree.getFirstChildTab(tab)) || (!tree.getPreviousSiblingTab(tab) && tree.getParentTab(tab))) nextTab.dir = 1;
return (noChild[tab._tPos] ? null : tree.getFirstChildTab(tab)) || tree.getPreviousSiblingTab(tab) || tree.getParentTab(tab);
}
}else{
if(!tab.nextSibling) nextTab.dir = -1;
return (dir) ? tab.nextSibling : tab.previousSibling;
}
};
let index = 0;
for(let n = nextTab(current); n && index === 0; n = nextTab(n)){
if(!n.CloseTabLater) index = n._tPos;
}
gBrowser.selectedTab = gBrowser.mTabContainer.childNodes[index];
})();
/* 閉じたタブを元に戻す(CloseTabLater) */
(function(){
if(1 <= window.CloseTabLaters.length){
gBrowser.selectedTab = gBrowser.mTabContainer.querySelector('tab.' + window.CloseTabLaters[0]);
}else{
undoCloseTab();
}
})();
/* ひとつ右のタブへ(CloseTabLater) */
(function(){
let index = null;
for(let i = gBrowser.mCurrentTab._tPos + 1; index === null; i++){
if(gBrowser.mTabContainer.childElementCount <= i) i = 0;
if(!gBrowser.mTabContainer.childNodes[i].CloseTabLater) index = i;
}
gBrowser.selectedTab = gBrowser.mTabContainer.childNodes[index];
})();
/* ひとつ左のタブへ(CloseTabLater) */
(function(){
let index = null;
for(let i = gBrowser.mCurrentTab._tPos - 1; index === null; i--){
if(i < 0) i = gBrowser.mTabContainer.childElementCount - 1;
if(!gBrowser.mTabContainer.childNodes[i].CloseTabLater) index = i;
}
gBrowser.selectedTab = gBrowser.mTabContainer.childNodes[index];
})();
// opacityじゃなくまるまるdisplay:noneでもいい!?
// 透明タブに限りEscで復活できてもいいかもしれない
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment