2018-12-13 23:55:34 +01:00
class Tabs _ttTab {
constructor ( p ) {
this . id = p . tab . id ;
this . pinned = p . tab . pinned ;
if ( document . getElementById ( p . tab . id ) != null && tt . tabs [ p . tab . id ] ) {
tt . tabs [ p . tab . id ] . GetFaviconAndTitle ( p . addCounter ) ;
return ;
}
let ClassList = p . tab . pinned ? "pin" : "tab" ;
if ( p . tab . discarded ) ClassList += " discarded" ;
if ( p . tab . attention ) ClassList += " attention" ;
if ( p . AdditionalClass ) ClassList += " " + p . AdditionalClass ;
if ( p . ExpandState ) ClassList += " " + p . ExpandState ;
let DIV _Tab = DOM _New ( "div" , undefined , { id : p . tab . id , className : ClassList } ) ;
let DIV _header = DOM _New ( "div" , DIV _Tab , { id : ( "tab_header_" + p . tab . id ) , className : ( opt . always _show _close && ! opt . never _show _close ) ? "tab_header close_show" : "tab_header" , draggable : ( ! p . SkipSetEvents ? true : false ) } ) ;
let DIV _expand = DOM _New ( "div" , DIV _header , { id : ( "exp_" + p . tab . id ) , className : "expand" } ) ;
let DIV _counter = DOM _New ( "div" , DIV _header , { id : ( "tab_counter_" + p . tab . id ) , className : "tab_counter" } ) ;
DOM _New ( "div" , DIV _counter , { id : ( "counter_number_" + p . tab . id ) , className : "counter_number" } ) ;
let DIV _title = DOM _New ( "div" , DIV _header , { id : ( "tab_title_" + p . tab . id ) , className : "tab_title" } ) ;
let DIV _close _button = DOM _New ( "div" , DIV _header , { id : ( "close_" + p . tab . id ) , className : ( opt . never _show _close ? "close hidden" : "close" ) } ) ;
DOM _New ( "div" , DIV _close _button , { id : ( "close_img_" + p . tab . id ) , className : ( opt . never _show _close ? "close_img hidden" : "close_img" ) } ) ;
let DIV _audio _indicator = DOM _New ( "div" , DIV _header , { id : ( "tab_mediaicon_" + p . tab . id ) , className : "tab_mediaicon" } ) ;
let DIV _children = DOM _New ( "div" , DIV _Tab , { id : ( "°" + p . tab . id ) , className : "children" } ) ;
DOM _New ( "div" , DIV _Tab , { id : ( "drag_indicator_" + p . tab . id ) , className : "drag_indicator" } ) ;
if ( ! p . SkipSetEvents ) {
DIV _children . onclick = function ( event ) {
if ( event . target == this && event . which == 1 ) DOM _Deselect ( ) ;
}
DIV _children . onmousedown = function ( event ) {
if ( event . target == this ) {
if ( event . which == 2 && event . target == this ) {
event . stopImmediatePropagation ( ) ;
Groups _ActionClickGroup ( this . parentNode , opt . midclick _group ) ;
}
if ( event . which == 3 ) Menu _ShowFGlobalMenu ( event ) ;
}
}
DIV _children . ondblclick = function ( event ) {
if ( event . target == this ) Groups _ActionClickGroup ( this . parentNode , opt . dbclick _group ) ;
}
DIV _expand . onmousedown = function ( event ) {
if ( tt . DOMmenu . style . top != "-1000px" ) Menu _HideMenus ( ) ;
if ( event . which == 1 && ! event . shiftKey && ! event . ctrlKey ) DOM _EventExpandBox ( this . parentNode . parentNode ) ;
}
DIV _expand . onmouseenter = function ( event ) {
this . classList . add ( "hover" ) ;
}
DIV _expand . onmouseleave = function ( event ) {
this . classList . remove ( "hover" ) ;
}
if ( ! opt . never _show _close ) {
DIV _close _button . onmousedown = function ( event ) {
event . stopImmediatePropagation ( ) ;
if ( event . which != 3 ) Tabs _CloseTabs ( [ parseInt ( this . parentNode . parentNode . id ) ] ) ;
}
DIV _close _button . onmouseenter = function ( event ) {
this . classList . add ( "close_hover" ) ;
}
DIV _close _button . onmouseleave = function ( event ) {
this . classList . remove ( "close_hover" ) ;
}
}
DIV _header . ondblclick = function ( event ) {
if ( event . target . classList && event . target . classList . contains ( "tab_header" ) ) Tabs _ActionClickTab ( this . parentNode , opt . dbclick _tab ) ;
}
DIV _header . onmousedown = function ( event ) {
if ( browserId == "V" ) {
chrome . windows . getCurrent ( { populate : false } , function ( window ) {
if ( tt . CurrentWindowId != window . id && window . focused ) location . reload ( ) ;
} ) ;
}
event . stopImmediatePropagation ( ) ;
if ( event . which == 1 ) {
if ( tt . DOMmenu . style . top != "-1000px" ) {
Menu _HideMenus ( ) ;
} else {
if ( event . shiftKey || event . ctrlKey ) {
DOM _Select ( event , this . parentNode ) ;
}
// let tabId = parseInt(this.parentNode.id);
// setTimeout(function() {
// if (tt.Dragging == false && !event.shiftKey && !event.ctrlKey && event.target.classList.contains("tab_header") && event.target.parentNode.classList.contains("selected") == false) {
// chrome.tabs.update(tabId, {active: true});
// }
// }, 90);
}
}
if ( event . which == 2 ) {
event . preventDefault ( ) ;
Tabs _ActionClickTab ( this . parentNode , opt . midclick _tab ) ;
}
if ( event . which == 3 ) Menu _ShowTabMenu ( this . parentNode , event ) ;
}
DIV _header . onclick = function ( event ) {
if ( ! event . shiftKey && ! event . ctrlKey ) {
DOM _Deselect ( ) ;
// let tabId = parseInt(this.parentNode.id);
if ( event . target . classList . contains ( "tab_header" ) ) {
chrome . tabs . update ( parseInt ( this . parentNode . id ) , { active : true } ) ;
// , function(tab) {
// if (was_selected) tt.tab[tab.id].Node.classList.add("selected");
// });
}
}
}
// DIV_header.onmouseup = function(event) {
// event.stopImmediatePropagation();
// if (tt.DOMmenu.style.top != "-1000px") {
// Menu_HideMenus();
// } else {
// if (event.which == 1 && !event.shiftKey && !event.ctrlKey && event.target.classList.contains("tab_header")) {
// DOM_Deselect();
// chrome.tabs.update(parseInt(this.parentNode.id), {active: true});
// }
// }
// }
DIV _header . onmouseover = function ( event ) {
this . classList . add ( "tab_header_hover" ) ;
if ( opt . never _show _close == false && opt . always _show _close == false ) this . classList . add ( "close_show" ) ;
}
DIV _header . onmouseleave = function ( event ) {
this . classList . remove ( "tab_header_hover" ) ;
if ( opt . never _show _close == false && opt . always _show _close == false ) this . classList . remove ( "close_show" ) ;
}
DIV _header . ondragstart = function ( event ) { // DRAG START
tt . Dragging = true ;
tt . DraggingGroup = false ;
event . stopPropagation ( ) ;
event . dataTransfer . setDragImage ( document . getElementById ( "DragImage" ) , 0 , 0 ) ;
event . dataTransfer . setData ( "text" , "" ) ;
event . dataTransfer . setData ( "SourceWindowId" , tt . CurrentWindowId ) ;
DOM _CleanUpDragAndDrop ( ) ;
let Nodes = [ ] ;
if ( this . parentNode . classList . contains ( "selected" ) ) {
DOM _FreezeSelection ( false ) ;
} else {
DOM _FreezeSelection ( true ) ;
DOM _SetClasses ( this . parentNode , [ "selected_temporarly" , "selected" ] , [ ] , [ ] ) ;
}
DOM _RemoveHeadersHoverClass ( ) ;
let selected = document . querySelectorAll ( ".selected, .selected .tab, .selected .folder" ) ;
for ( let s of selected ) {
s . classList . add ( "dragged_tree" ) ;
if ( s . classList . contains ( "pin" ) ) {
tt . DraggingPin = true ;
Nodes . push ( { id : s . id , parent : s . parentNode . id , selected : s . classList . contains ( "selected" ) , temporary : s . classList . contains ( "selected_temporarly" ) , NodeClass : "pin" } ) ;
}
if ( s . classList . contains ( "tab" ) ) {
tt . DraggingTab = true ;
Nodes . push ( { id : s . id , parent : s . parentNode . id , selected : s . classList . contains ( "selected" ) , temporary : s . classList . contains ( "selected_temporarly" ) , NodeClass : "tab" } ) ;
}
if ( s . classList . contains ( "folder" ) ) {
tt . DraggingFolder = true ;
Nodes . push ( { id : s . id , parent : s . parentNode . id , selected : s . classList . contains ( "selected" ) , temporary : s . classList . contains ( "selected_temporarly" ) , NodeClass : "folder" , index : ( tt . folders [ s . id ] ? tt . folders [ s . id ] . index : 0 ) , name : ( tt . folders [ s . id ] ? tt . folders [ s . id ] . name : labels . noname _group ) , expand : ( tt . folders [ s . id ] ? tt . folders [ s . id ] . expand : "" ) } ) ;
}
}
if ( opt . max _tree _drag _drop && opt . max _tree _depth >= 0 ) {
let dragged _tree = document . querySelectorAll ( ".dragged_tree .tab, .dragged_tree .folder" ) ;
for ( let s of dragged _tree ) {
let parents = DOM _GetParentsByClass ( s . parentNode , "dragged_tree" ) ;
if ( parents . length > tt . DragTreeDepth ) tt . DragTreeDepth = parents . length ;
}
} else {
tt . DragTreeDepth = - 1 ;
}
let Parents = DOM _GetAllParents ( this . parentNode ) ;
for ( let s of Parents ) {
if ( s . classList && ( s . classList . contains ( "tab" ) || s . classList . contains ( "folder" ) ) ) s . classList . add ( "dragged_parents" ) ;
}
event . dataTransfer . setData ( "Nodes" , JSON . stringify ( Nodes ) ) ;
event . dataTransfer . setData ( "NodesTypes" , JSON . stringify ( { DraggingGroup : tt . DraggingGroup , DraggingPin : tt . DraggingPin , DraggingTab : tt . DraggingTab , DraggingFolder : tt . DraggingFolder } ) ) ;
chrome . runtime . sendMessage ( { command : "drag_start" , DragTreeDepth : tt . DragTreeDepth , DraggingGroup : tt . DraggingGroup , DraggingPin : tt . DraggingPin , DraggingTab : tt . DraggingTab , DraggingFolder : tt . DraggingFolder } ) ;
}
DIV _header . ondragenter = function ( event ) {
this . classList . remove ( "tab_header_hover" ) ;
}
DIV _header . ondragleave = function ( event ) {
DOM _RemoveHighlight ( ) ;
}
DIV _header . ondragover = function ( event ) {
if ( tt . DraggingGroup == false && ( tt . DraggingPin || tt . DraggingTab || tt . DraggingFolder ) && this . parentNode . classList . contains ( "dragged_tree" ) == false ) {
if ( this . parentNode . classList . contains ( "pin" ) ) {
if ( this . parentNode . classList . contains ( "before" ) == false && event . layerX < this . clientWidth / 2 ) {
DOM _RemoveHighlight ( ) ;
DOM _SetClasses ( this . parentNode , [ "before" , "highlighted_drop_target" ] , [ "after" ] , [ ] ) ;
}
if ( this . parentNode . classList . contains ( "after" ) == false && event . layerX >= this . clientWidth / 2 ) {
DOM _RemoveHighlight ( ) ;
DOM _SetClasses ( this . parentNode , [ "after" , "highlighted_drop_target" ] , [ "before" ] , [ ] ) ;
}
}
if ( this . parentNode . classList . contains ( "tab" ) ) {
let TabDepth = Tabs _GetTabDepthInTree ( this ) ;
let PDepth = TabDepth + tt . DragTreeDepth ;
let PIsGroup = this . parentNode . parentNode . parentNode . classList . contains ( "group" ) ;
// let PIsTab = this.parentNode.parentNode.parentNode.classList.contains("tab");
let PIsFolder = this . parentNode . parentNode . parentNode . classList . contains ( "folder" ) ;
let PIsDraggedParents = this . parentNode . classList . contains ( "dragged_parents" ) ;
if ( ( PIsFolder == tt . DraggingFolder || tt . DraggingFolder == false || PIsGroup == true ) && this . parentNode . classList . contains ( "before" ) == false && event . layerY < this . clientHeight / 3 && ( PDepth <= opt . max _tree _depth + 1 || opt . max _tree _depth < 0 || opt . max _tree _drag _drop == false || PIsDraggedParents == true ) ) {
DOM _RemoveHighlight ( ) ;
DOM _SetClasses ( this . parentNode , [ "before" , "highlighted_drop_target" ] , [ "inside" , "after" ] , [ ] ) ;
}
if ( tt . DraggingFolder == false && this . parentNode . classList . contains ( "inside" ) == false && event . layerY > this . clientHeight / 3 && event . layerY <= 2 * ( this . clientHeight / 3 ) && ( PDepth <= opt . max _tree _depth || opt . max _tree _depth < 0 || opt . max _tree _drag _drop == false || PIsDraggedParents == true ) ) {
DOM _RemoveHighlight ( ) ;
DOM _SetClasses ( this . parentNode , [ "inside" , "highlighted_drop_target" ] , [ "before" , "after" ] , [ ] ) ;
}
if ( ( PIsFolder == tt . DraggingFolder || tt . DraggingFolder == false || PIsGroup == true ) && this . parentNode . classList . contains ( "after" ) == false && this . parentNode . classList . contains ( "o" ) == false && event . layerY > 2 * ( this . clientHeight / 3 ) && ( PDepth <= opt . max _tree _depth + 1 || opt . max _tree _depth < 0 || opt . max _tree _drag _drop == false || PIsDraggedParents == true ) ) {
DOM _RemoveHighlight ( ) ;
DOM _SetClasses ( this . parentNode , [ "after" , "highlighted_drop_target" ] , [ "before" , "inside" ] , [ ] ) ;
}
}
}
if ( opt . open _tree _on _hover && tt . DragOverId != this . id ) {
if ( this . parentNode . classList . contains ( "c" ) && this . parentNode . classList . contains ( "dragged_tree" ) == false ) {
clearTimeout ( tt . DragOverTimer ) ;
tt . DragOverId = this . id ;
let This = this ;
tt . DragOverTimer = setTimeout ( function ( ) {
if ( tt . DragOverId == This . id ) DOM _SetClasses ( This . parentNode , [ "o" ] , [ "c" ] , [ ] ) ;
} , 1500 ) ;
}
}
}
DIV _header . ondragend = function ( event ) {
if ( opt . open _tree _on _hover ) {
clearTimeout ( tt . DragOverTimer ) ;
tt . DragOverId = "" ;
}
setTimeout ( function ( ) { DOM _CleanUpDragAndDrop ( ) ; } , 300 ) ;
setTimeout ( function ( ) { chrome . runtime . sendMessage ( { command : "drag_end" } ) ; } , 500 ) ;
}
DIV _audio _indicator . onmousedown = function ( event ) {
event . stopImmediatePropagation ( ) ;
if ( event . which == 1 && ( this . parentNode . parentNode . classList . contains ( "audible" ) || this . parentNode . parentNode . classList . contains ( "muted" ) ) ) {
chrome . tabs . get ( parseInt ( this . parentNode . parentNode . id ) , function ( tab ) {
if ( tab ) chrome . tabs . update ( tab . id , { muted : ! tab . mutedInfo . muted } ) ;
} ) ;
}
}
}
let parent ;
if ( p . tab . pinned == true ) {
parent = document . getElementById ( "pin_list" ) ;
} else {
if ( p . ParentId == false || p . ParentId == undefined || p . ParentId == "pin_list" ) {
parent = document . getElementById ( "°" + tt . active _group ) ;
} else {
parent = document . getElementById ( p . ParentId ) ;
if ( parent == null || parent . classList . contains ( "pin" ) || parent . parentNode . classList . contains ( "pin" ) ) {
parent = document . getElementById ( "°" + tt . active _group ) ;
} else {
parent = document . getElementById ( "°" + p . ParentId ) ;
if ( parent . children . length == 0 ) DOM _SetClasses ( parent . parentNode , [ "o" ] , [ "c" ] , [ ] ) ;
}
}
}
if ( p . Append == true && parent ) parent . appendChild ( DIV _Tab ) ;
if ( ( p . Append == false || p . Append == undefined ) && parent ) { parent . prepend ( DIV _Tab ) ; }
if ( p . InsertAfterId ) {
let After = document . getElementById ( p . InsertAfterId ) ;
if ( After != null ) {
if ( ( p . tab . pinned && After . classList . contains ( "pin" ) ) || ( p . tab . pinned == false && ( After . classList . contains ( "tab" ) || After . classList . contains ( "folder" ) ) ) ) {
DOM _InsterAfterNode ( DIV _Tab , After ) ;
} else {
parent . appendChild ( DIV _Tab ) ;
}
} else {
parent . appendChild ( DIV _Tab ) ;
}
}
this . Node = DIV _Tab ;
this . title = DIV _title ;
if ( ! p . SkipFavicon ) this . GetFaviconAndTitle ( p . addCounter ) ;
if ( ! p . SkipMediaIcon ) this . RefreshMediaIcon ( p . tab . id ) ;
if ( p . RefreshDiscarded ) this . RefreshDiscarded ( ) ;
if ( p . tab . active && ! p . SkipSetActive ) Tabs _SetActiveTab ( p . tab . id ) ;
if ( p . Scroll ) this . ScrollToTab ( ) ;
}
RemoveTab ( ) {
if ( opt . debug ) Utils _log ( "f: RemoveTab, tabId: " + this . id ) ;
if ( this . Node != null ) {
this . Node . parentNode . removeChild ( this . Node ) ;
if ( tt . tabs [ this . id ] ) delete tt . tabs [ this . id ] ;
}
}
ScrollToTab ( ) {
let Tab = this . Node ;
let P = document . getElementById ( "pin_list" ) ;
let G = document . getElementById ( tt . active _group ) ;
if ( Tab != null ) {
if ( Tab . classList . contains ( "pin" ) ) {
if ( Tab . getBoundingClientRect ( ) . left - P . getBoundingClientRect ( ) . left < 0 ) {
P . scrollLeft = P . scrollLeft + Tab . getBoundingClientRect ( ) . left - P . getBoundingClientRect ( ) . left - 2 ;
} else {
if ( Tab . getBoundingClientRect ( ) . left - P . getBoundingClientRect ( ) . left > G . getBoundingClientRect ( ) . width - document . querySelector ( ".tab_header" ) . getBoundingClientRect ( ) . width ) {
P . scrollLeft = P . scrollLeft + Tab . getBoundingClientRect ( ) . left - P . getBoundingClientRect ( ) . left - P . getBoundingClientRect ( ) . width + document . querySelector ( ".tab_header" ) . getBoundingClientRect ( ) . width + 2 ;
}
}
} else if ( Tab . classList . contains ( "tab" ) && document . querySelector ( "#" + tt . active _group + " [id='" + this . id + "']" ) != null ) {
let Parents = DOM _GetParentsByClass ( Tab , "c" ) ;
if ( Parents . length > 0 ) {
for ( let s of Parents ) {
DOM _SetClasses ( s , [ "o" ] , [ "c" ] , [ ] ) ;
}
}
if ( Tab . getBoundingClientRect ( ) . top - G . getBoundingClientRect ( ) . top < 0 ) {
G . scrollTop = G . scrollTop + Tab . getBoundingClientRect ( ) . top - G . getBoundingClientRect ( ) . top - 2 ;
} else {
if ( Tab . getBoundingClientRect ( ) . top - G . getBoundingClientRect ( ) . top > G . getBoundingClientRect ( ) . height - document . querySelector ( ".tab_header" ) . getBoundingClientRect ( ) . height ) {
G . scrollTop = G . scrollTop + Tab . getBoundingClientRect ( ) . top - G . getBoundingClientRect ( ) . top - G . getBoundingClientRect ( ) . height + document . querySelector ( ".tab_header" ) . getBoundingClientRect ( ) . height + 10 ;
}
}
}
}
}
SetTabClass ( pin ) {
let GroupList = document . getElementById ( "°" + tt . active _group ) ;
let Tab = this . Node ;
if ( Tab != null ) {
if ( pin ) {
if ( Tab . parentNode . id != "pin_list" ) document . getElementById ( "pin_list" ) . appendChild ( Tab ) ;
DOM _SetClasses ( Tab , [ "pin" ] , [ "tab" , "o" , "c" ] , [ ] ) ;
if ( Tab . childNodes [ 1 ] . childNodes . length > 0 ) { // flatten out children
let tabs = document . querySelectorAll ( "#°" + Tab . id + " .pin, #°" + Tab . id + " .tab" ) ;
for ( let tab of tabs ) {
DOM _SetClasses ( tab , [ "pin" ] , [ "tab" , "o" , "c" ] , [ ] ) ;
DOM _InsterAfterNode ( tab , Tab ) ;
chrome . tabs . update ( parseInt ( tab . id ) , { pinned : true } ) ;
}
let folders = document . querySelectorAll ( "#°" + Tab . id + " .folder" ) ;
for ( let i = folders . length - 1 ; i >= 0 ; i -- ) {
GroupList . prepend ( folders [ i ] ) ;
}
}
chrome . tabs . update ( parseInt ( Tab . id ) , { pinned : true } ) ;
} else {
if ( Tab . parentNode . id == "pin_list" ) { // if coming from pin_list
if ( GroupList . childNodes . length > 0 ) {
GroupList . insertBefore ( Tab , GroupList . childNodes [ 0 ] ) ;
} else {
GroupList . appendChild ( Tab ) ;
}
}
DOM _SetClasses ( Tab , [ "tab" ] , [ "pin" , "attention" ] , [ ] ) ;
DOM _RefreshExpandStates ( ) ;
chrome . tabs . update ( parseInt ( Tab . id ) , { pinned : false } ) ;
}
DOM _RefreshGUI ( ) ;
}
}
DuplicateTab ( ) {
let OriginalTabNode = this . Node ;
chrome . tabs . duplicate ( parseInt ( this . id ) , function ( tab ) {
let DupRetry = setInterval ( function ( ) {
let DupTab = document . getElementById ( tab . id ) ;
if ( DupTab != null && OriginalTabNode != null ) {
if ( browserId == "F" && tab . pinned ) DOM _SetClasses ( DupTab , [ "pin" ] , [ "tab" ] , [ ] ) ;
DOM _InsterAfterNode ( DupTab , OriginalTabNode ) ;
DOM _RefreshExpandStates ( ) ;
tt . schedule _update _data ++ ;
DOM _RefreshCounters ( ) ;
clearInterval ( DupRetry ) ;
}
} , 10 ) ;
setTimeout ( function ( ) {
if ( DupRetry ) clearInterval ( DupRetry ) ;
} , 500 ) ;
} ) ;
}
GetFaviconAndTitle ( addCounter ) {
let t = document . getElementById ( this . id ) ;
let tTitle = this . title ;
if ( t != null ) {
chrome . tabs . get ( parseInt ( t . id ) , async function ( tab ) {
if ( tab ) {
let title = tab . title ? tab . title : tab . url ;
let tHeader = t . childNodes [ 0 ] ;
if ( tab . status == "complete" || tab . discarded ) {
t . classList . remove ( "loading" ) ;
tTitle . textContent = title ;
tHeader . title = title ;
if ( opt . show _counter _tabs _hints ) tHeader . setAttribute ( "tabTitle" , title ) ;
let Img = new Image ( ) ;
let CachedFavicon = browserId == "F" ? await browser . sessions . getTabValue ( tab . id , "CachedFaviconUrl" ) : "chrome://favicon/" + tab . url ;
let TryCases = [ tab . favIconUrl , CachedFavicon , "./theme/icon_empty.svg" ] ;
Tabs _LoadFavicon ( tab . id , Img , TryCases , tHeader , 0 ) ;
}
if ( tab . status == "loading" && tab . discarded == false ) {
title = tab . title ? tab . title : labels . loading ;
t . classList . add ( "loading" ) ;
tHeader . style . backgroundImage = "" ;
tHeader . title = labels . loading ;
if ( opt . show _counter _tabs _hints ) tHeader . setAttribute ( "tabTitle" , labels . loading ) ;
tTitle . textContent = labels . loading ;
setTimeout ( function ( ) {
if ( document . getElementById ( tab . id ) != null && tt . tabs [ tab . id ] ) tt . tabs [ tab . id ] . GetFaviconAndTitle ( addCounter ) ;
} , 1000 ) ;
}
if ( addCounter && ( opt . show _counter _tabs || opt . show _counter _tabs _hints ) ) tt . tabs [ t . id ] . RefreshTabCounter ( ) ;
}
} ) ;
}
}
RefreshDiscarded ( ) { // set discarded class
let t = document . getElementById ( this . id ) ;
if ( t != null ) {
chrome . tabs . get ( parseInt ( t . id ) , function ( tab ) {
if ( tab ) {
if ( tab . discarded ) {
DOM _SetClasses ( t , [ "discarded" ] , [ "audible" , "muted" ] , [ ] ) ;
} else {
t . classList . remove ( "discarded" ) ;
}
}
} ) ;
}
}
SetAttentionIcon ( ) { // set attention class
let t = document . getElementById ( this . id ) ;
if ( t != null ) t . classList . add ( "attention" ) ;
}
RefreshMediaIcon ( ) { // change media icon
let t = document . getElementById ( this . id ) ;
if ( t != null ) {
chrome . tabs . get ( parseInt ( t . id ) , function ( tab ) {
if ( tab ) {
if ( tab . mutedInfo . muted && ! tab . discarded ) DOM _SetClasses ( t , [ "muted" ] , [ "audible" ] , [ ] ) ;
if ( ! tab . mutedInfo . muted && tab . audible && ! tab . discarded ) DOM _SetClasses ( t , [ "audible" ] , [ "muted" ] , [ ] ) ;
if ( ( ! tab . mutedInfo . muted && ! tab . audible ) || tab . discarded ) DOM _SetClasses ( t , [ ] , [ "audible" , "muted" ] , [ ] ) ;
}
} ) ;
}
}
RefreshTabCounter ( ) {
let t = document . getElementById ( this . id ) ;
if ( t != null && t . childNodes [ 0 ] ) {
let title = t . childNodes [ 0 ] . getAttribute ( "tabTitle" ) ;
if ( t != null && title != null ) {
if ( t . classList . contains ( "o" ) || t . classList . contains ( "c" ) ) {
if ( opt . show _counter _tabs ) t . childNodes [ 0 ] . childNodes [ 1 ] . childNodes [ 0 ] . textContent = document . querySelectorAll ( "[id='" + t . id + "'] .tab" ) . length ;
if ( opt . show _counter _tabs _hints ) t . childNodes [ 0 ] . title = ( document . querySelectorAll ( "[id='" + t . id + "'] .tab" ) . length + " • " ) + title ;
} else {
t . childNodes [ 0 ] . title = title ;
}
}
}
}
2018-05-22 02:11:29 +02:00
}
2018-03-13 14:39:34 +01:00
2018-12-13 23:55:34 +01:00
async function Tabs _LoadFavicon ( tabId , Img , TryUrls , TabHeaderNode , i ) {
if ( TabHeaderNode ) {
Img . src = TryUrls [ i ] ;
Img . onload = function ( ) {
TabHeaderNode . style . backgroundImage = "url(" + TryUrls [ i ] + ")" ;
if ( browserId == "F" ) browser . sessions . setTabValue ( tabId , "CachedFaviconUrl" , TryUrls [ i ] ) ; // cache Firefox favicon - solution for bug with empty favicons in unloaded tabs
} ;
Img . onerror = function ( ) {
if ( i < TryUrls . length ) Tabs _LoadFavicon ( tabId , Img , TryUrls , TabHeaderNode , ( i + 1 ) ) ;
}
}
2017-07-26 22:23:39 +02:00
}
2018-03-13 14:39:34 +01:00
2018-12-13 23:55:34 +01:00
async function Tabs _SaveTabs ( ) {
setInterval ( function ( ) {
2018-12-25 23:10:32 +01:00
if ( opt . debug ) Utils _log ( "f: Tabs_SaveTabs" ) ;
2018-12-13 23:55:34 +01:00
if ( tt . schedule _update _data > 1 ) tt . schedule _update _data = 1 ;
if ( tt . schedule _update _data > 0 ) {
let pins _data = [ ] ;
let tabs _data = [ ] ;
for ( let tabId in tt . tabs ) {
if ( tt . tabs [ tabId ] . Node != null && tt . tabs [ tabId ] . Node . parentNode != null ) {
if ( tt . tabs [ tabId ] . pinned ) {
pins _data . push ( { id : tabId , parent : "pin_list" , index : Array . from ( tt . tabs [ tabId ] . Node . parentNode . children ) . indexOf ( tt . tabs [ tabId ] . Node ) , expand : "" } ) ;
} else {
tabs _data . push ( { id : tabId , parent : tt . tabs [ tabId ] . Node . parentNode . parentNode . id , index : Array . from ( tt . tabs [ tabId ] . Node . parentNode . children ) . indexOf ( tt . tabs [ tabId ] . Node ) , expand : ( tt . tabs [ tabId ] . Node . classList . contains ( "c" ) ? "c" : ( tt . tabs [ tabId ] . Node . classList . contains ( "o" ) ? "o" : "" ) ) } ) ;
}
}
}
chrome . runtime . sendMessage ( { command : "update_all_tabs" , pins : pins _data , tabs : tabs _data } ) ;
tt . schedule _update _data -- ;
}
} , 1000 ) ;
2017-07-26 22:23:39 +02:00
}
2018-03-13 14:39:34 +01:00
2018-12-13 23:55:34 +01:00
async function Tabs _RearrangeBrowserTabs ( ) {
2018-12-25 23:10:32 +01:00
if ( opt . debug ) Utils _log ( "f: Tabs_RearrangeBrowserTabs" ) ;
2018-12-13 23:55:34 +01:00
setInterval ( function ( ) {
if ( tt . schedule _rearrange _tabs > 0 ) {
tt . schedule _rearrange _tabs -- ;
if ( opt . debug ) Utils _log ( "f: RearrangeBrowserTabs" ) ;
chrome . tabs . query ( { currentWindow : true } , function ( tabs ) {
let ttTabIds = Array . prototype . map . call ( document . querySelectorAll ( ".pin, .tab" ) , function ( s ) { return parseInt ( s . id ) ; } ) ;
let tabIds = Array . prototype . map . call ( tabs , function ( t ) { return t . id ; } ) ;
Tabs _RearrangeBrowserTabsLoop ( ttTabIds , tabIds , ttTabIds . length - 1 ) ;
} ) ;
}
} , 1000 ) ;
2017-07-26 22:23:39 +02:00
}
2018-03-13 14:39:34 +01:00
2018-12-13 23:55:34 +01:00
async function Tabs _RearrangeBrowserTabsLoop ( ttTabIds , tabIds , tabIndex ) {
if ( opt . debug ) Utils _log ( "f: RearrangeBrowserTabsLoop" ) ;
if ( tabIndex >= 0 && tt . schedule _rearrange _tabs == 0 ) {
if ( ttTabIds [ tabIndex ] != tabIds [ tabIndex ] ) chrome . tabs . move ( ttTabIds [ tabIndex ] , { index : tabIndex } ) ;
setTimeout ( function ( ) {
Tabs _RearrangeBrowserTabsLoop ( ttTabIds , tabIds , ( tabIndex - 1 ) ) ;
} , 0 ) ;
}
2017-07-26 22:23:39 +02:00
}
2018-03-13 14:39:34 +01:00
2018-12-13 23:55:34 +01:00
function Tabs _RearrangeTree ( TTtabs , TTfolders , show _finish _in _status ) {
2018-12-25 23:10:32 +01:00
if ( opt . debug ) Utils _log ( "f: Tabs_RearrangeTree" ) ;
2018-12-13 23:55:34 +01:00
Manager _ShowStatusBar ( { show : true , spinner : true , message : chrome . i18n . getMessage ( "status_bar_rearranging_tabs" ) } ) ;
let Nodes = document . querySelectorAll ( ".pin, .tab, .folder" ) ;
for ( let Node of Nodes ) {
let Sibling = Node . nextElementSibling ;
if ( Sibling ) {
let NodeIndex = TTtabs [ Node . id ] ? TTtabs [ Node . id ] . index : ( TTfolders [ Node . id ] ? TTfolders [ Node . id ] . index : undefined ) ;
while ( Sibling && NodeIndex ) {
let SiblingIndex = TTtabs [ Sibling . id ] ? TTtabs [ Sibling . id ] . index : ( TTfolders [ Sibling . id ] ? TTfolders [ Sibling . id ] . index : 0 ) ;
if ( NodeIndex > SiblingIndex ) DOM _InsterAfterNode ( Node , Sibling ) ;
Sibling = Sibling . nextElementSibling ? Sibling . nextElementSibling : false ;
}
}
if ( show _finish _in _status ) Manager _ShowStatusBar ( { show : true , spinner : false , message : chrome . i18n . getMessage ( "status_bar_rearranging_finished" ) , hideTimeout : 1000 } ) ;
}
2017-07-26 22:23:39 +02:00
}
2018-03-13 14:39:34 +01:00
2018-12-13 23:55:34 +01:00
function Tabs _Detach ( Nodes , NodesTypes , Group ) {
if ( opt . debug ) Utils _log ( "f: Detach" ) ;
let folderNodes = { } ;
let TabsIds = [ ] ;
for ( let Node of Nodes ) {
if ( Node . NodeClass == "folder" ) folderNodes [ Node . id ] = { id : Node . id , parent : ( Node . parent ) . substr ( 1 ) , name : Node . name , index : Node . index , expand : Node . expand } ;
if ( Node . NodeClass == "pin" ) TabsIds . push ( parseInt ( Node . id ) ) ;
if ( Node . NodeClass == "tab" ) TabsIds . push ( parseInt ( Node . id ) ) ;
}
chrome . windows . get ( tt . CurrentWindowId , { populate : true } , function ( window ) {
if ( window . tabs . length == 1 ) return ;
if ( TabsIds . length == window . tabs . length ) {
if ( opt . debug ) Utils _log ( "You are trying to detach all tabs! Skipping!" ) ;
return ;
}
let params = TabsIds . length > 0 ? { tabId : TabsIds [ 0 ] , state : window . state } : { state : window . state } ;
chrome . windows . create ( params , function ( new _window ) {
chrome . tabs . update ( new _window . tabs [ 0 ] . id , { active : true } ) ;
chrome . runtime . sendMessage ( { command : "get_groups" , windowId : new _window . id } , function ( g ) {
if ( NodesTypes . DraggingGroup ) {
let GroupsToDetach = Object . assign ( { } , g ) ; // if there will be a multi groups selection, below I will need for each group loop
GroupsToDetach [ Group . id ] = Group ;
chrome . runtime . sendMessage ( { command : "save_groups" , groups : GroupsToDetach , windowId : new _window . id } ) ;
setTimeout ( function ( ) { Groups _GroupRemove ( Group . id , false ) ; } , 2000 ) ;
}
chrome . runtime . sendMessage ( { command : "save_folders" , folders : folderNodes , windowId : new _window . id } ) ;
for ( let Node of Nodes ) {
if ( Node . NodeClass == "pin" ) {
chrome . tabs . update ( parseInt ( Node . id ) , { pinned : true } ) ;
chrome . runtime . sendMessage ( { command : "update_tab" , tabId : Node . id , tab : { parent : "pin_list" } } ) ;
}
if ( Node . NodeClass == "tab" ) chrome . runtime . sendMessage ( { command : "update_tab" , tabId : Node . id , tab : { parent : ( Node . parent ) . substr ( 1 ) } } ) ;
if ( Node . NodeClass == "folder" ) Folders _RemoveFolder ( Node . id ) ;
}
if ( TabsIds . length > 1 ) {
TabsIds . splice ( 0 , 1 ) ;
chrome . tabs . move ( TabsIds , { windowId : new _window . id , index : - 1 } , function ( MovedTabs ) {
for ( let Node of Nodes ) {
if ( Node . NodeClass == "pin" ) { chrome . tabs . update ( parseInt ( Node . id ) , { pinned : true } ) ; }
if ( Node . NodeClass == "folder" ) { Folders _RemoveFolder ( Node . id ) ; }
}
let Stop = 500 ;
let DetachNodes = setInterval ( function ( ) {
Stop -- ;
let all _moved = true ;
for ( let Node of Nodes ) {
if ( document . getElementById ( Node . id ) != null ) all _moved = false ;
if ( Node . NodeClass == "pin" ) chrome . runtime . sendMessage ( { command : "update_tab" , tabId : Node . id , tab : { parent : "pin_list" } } ) ;
if ( Node . NodeClass == "tab" ) chrome . runtime . sendMessage ( { command : "update_tab" , tabId : Node . id , tab : { parent : ( Node . parent ) . substr ( 1 ) } } ) ;
}
if ( all _moved || Stop < 0 ) {
setTimeout ( function ( ) {
clearInterval ( DetachNodes ) ;
} , 300 ) ;
}
} , 100 ) ;
} ) ;
}
} ) ;
} ) ;
} ) ;
2018-01-01 19:50:56 +01:00
}
2018-03-13 14:39:34 +01:00
2018-12-13 23:55:34 +01:00
function Tabs _DiscardTabs ( tabsIds ) {
let delay = 100 ;
let tabNode = document . getElementById ( tabsIds [ 0 ] ) ;
if ( tabNode == null || tabNode . classList . contains ( "discarded" ) || tabNode . classList . contains ( "active_tab" ) ) {
delay = 5 ;
} else {
chrome . tabs . discard ( tabsIds [ 0 ] ) ;
}
tabsIds . splice ( 0 , 1 ) ;
if ( tabsIds . length > 0 ) {
setTimeout ( function ( ) {
Tabs _DiscardTabs ( tabsIds ) ;
} , delay ) ;
}
2017-07-26 22:23:39 +02:00
}
2018-03-13 14:39:34 +01:00
2018-12-13 23:55:34 +01:00
function Tabs _FindTab ( input ) { // find and select tabs
let ButtonFilterClear = document . getElementById ( "button_filter_clear" ) ;
let Nodes = document . querySelectorAll ( ".filtered, .highlighted_search" ) ;
for ( let s of Nodes ) {
DOM _SetClasses ( s , [ ] , [ "selected" , "selected_last" , "filtered" , "highlighted_search" ] , [ ] ) ;
}
if ( input . length == 0 ) {
document . getElementById ( "filter_box" ) . value = "" ;
ButtonFilterClear . style . opacity = "0" ; ButtonFilterClear . title = "" ;
return ;
} else {
ButtonFilterClear . style . opacity = "1" ; ButtonFilterClear . title = labels . clear _filter ;
}
tt . SearchIndex = 0 ;
let FilterType = document . getElementById ( "button_filter_type" ) ;
let searchUrl = FilterType . classList . contains ( "url" ) ;
let searchTitle = FilterType . classList . contains ( "title" ) ;
let query = { windowId : tt . CurrentWindowId , pinned : false } ;
if ( input == "*audible" ) query = { windowId : tt . CurrentWindowId , discarded : false , audible : true , muted : false , pinned : false } ;
if ( input == "*muted" ) query = { windowId : tt . CurrentWindowId , discarded : false , muted : true , pinned : false } ;
if ( input == "*unloaded" ) query = { windowId : tt . CurrentWindowId , discarded : true , pinned : false } ;
if ( input == "*loaded" ) query = { windowId : tt . CurrentWindowId , discarded : false , pinned : false } ;
chrome . tabs . query ( query , function ( tabs ) {
for ( let Tab of tabs ) {
let t = document . getElementById ( Tab . id ) ;
if ( input == "*audible" || input == "*muted" || input == "*unloaded" || input == "*loaded" ) {
DOM _SetClasses ( t , [ "filtered" , "selected" ] , [ ] , [ ] ) ;
} else {
if ( searchUrl ) {
if ( Tab . url . toLowerCase ( ) . match ( input . toLowerCase ( ) ) ) DOM _SetClasses ( t , [ "filtered" , "selected" ] , [ ] , [ ] ) ;
}
if ( searchTitle ) {
if ( Tab . title . toLowerCase ( ) . match ( input . toLowerCase ( ) ) ) DOM _SetClasses ( t , [ "filtered" , "selected" ] , [ ] , [ ] ) ;
}
}
}
} ) ;
2017-07-26 22:23:39 +02:00
}
2018-03-13 14:39:34 +01:00
2018-12-13 23:55:34 +01:00
function Tabs _CloseTabs ( tabsIds ) {
if ( opt . debug ) Utils _log ( "f: Tabs_CloseTabs, tabsIds are: " + JSON . stringify ( tabsIds ) ) ;
for ( let tabId of tabsIds ) {
let t = document . getElementById ( tabId ) ;
if ( t != null ) t . classList . add ( "will_be_closed" ) ;
}
let activeTab = document . querySelector ( ".pin.active_tab, #" + tt . active _group + " .tab.active_tab" ) ;
if ( activeTab != null && tabsIds . indexOf ( parseInt ( activeTab . id ) ) != - 1 ) Tabs _SwitchActiveTabBeforeClose ( tt . active _group ) ;
setTimeout ( function ( ) {
for ( let tabId of tabsIds ) {
let t = document . getElementById ( tabId ) ;
if ( t != null && t . classList . contains ( "pin" ) && opt . allow _pin _close ) {
t . parentNode . removeChild ( t ) ;
chrome . tabs . update ( tabId , { pinned : false } ) ;
chrome . runtime . sendMessage ( { command : "update_tab" , tabId : tabId , tab : { parent : "pin_list" } } ) ;
}
if ( tabId == tabsIds [ tabsIds . length - 1 ] ) {
setTimeout ( function ( ) { chrome . tabs . remove ( tabsIds , null ) ; } , 10 ) ;
DOM _RefreshGUI ( ) ;
}
}
} , 200 ) ;
2017-07-26 22:23:39 +02:00
}
2018-03-13 14:39:34 +01:00
2018-12-13 23:55:34 +01:00
function Tabs _OpenNewTab ( pin , InsertAfterNode , AppendToNode ) {
// if (pin) {
chrome . tabs . create ( { pinned : pin } , function ( tab ) {
// console.log(tt.tabs[tab.id])
let Retry = setInterval ( function ( ) {
if ( tt . tabs [ tab . id ] ) {
if ( InsertAfterNode ) {
DOM _InsterAfterNode ( tt . tabs [ tab . id ] . Node , InsertAfterNode ) ;
}
if ( AppendToNode ) {
DOM _AppendToNode ( tt . tabs [ tab . id ] . Node , AppendToNode ) ;
}
tt . schedule _update _data ++ ;
clearInterval ( Retry ) ;
}
} , 10 ) ;
setTimeout ( function ( ) {
if ( Retry ) clearInterval ( Retry ) ;
} , 500 ) ;
if ( ! pin && opt . move _tabs _on _url _change == "from_empty" ) chrome . runtime . sendMessage ( { command : "remove_tab_from_empty_tabs" , tabId : tab . id } ) ;
// if (InsertAfterNode && tt.tabs[tab.id]) {
// let parent = document.getElementById("#pin_list");
// if (parent != null && tt.tabs[tab.id]) parent.appendChild(tt.tabs[tab.id].Node);
// }
} ) ;
// } else {
// chrome.tabs.create({}, function(tab) {
// if (parentId) {
// let parent = document.getElementById("#°"+parentId);
// if (parent != null && tt.tabs[tab.id]) parent.appendChild(tt.tabs[tab.id].Node);
// tt.schedule_update_data++;
// }
// });
// }
2017-11-12 22:00:40 +01:00
}
2018-03-13 14:39:34 +01:00
2018-12-13 23:55:34 +01:00
function Tabs _GetTabDepthInTree ( Node ) {
let Depth = 0 ;
let ParentNode = Node ;
if ( ParentNode == null ) return Parents ;
let Stop = false ;
while ( ! Stop && ParentNode . parentNode != null ) {
if ( ParentNode . parentNode . classList != undefined ) {
if ( ParentNode . parentNode . classList . contains ( "tab" ) ) Depth ++ ;
if ( ParentNode . parentNode . classList . contains ( "folder" ) || ParentNode . parentNode . classList . contains ( "group" ) ) {
Stop = true ;
} else {
ParentNode = ParentNode . parentNode ;
}
} else {
Stop = true ;
}
}
return Depth ;
2018-05-22 02:11:29 +02:00
}
2018-12-13 23:55:34 +01:00
function Tabs _ActionClickTab ( TabNode , bgOption ) {
if ( bgOption == "new_tab" ) Tabs _OpenNewTab ( TabNode . classList . contains ( "pin" ) , TabNode ) ;
if ( bgOption == "expand_collapse" ) DOM _EventExpandBox ( TabNode ) ;
if ( bgOption == "close_tab" ) {
if ( ( TabNode . classList . contains ( "pin" ) && opt . allow _pin _close ) || TabNode . classList . contains ( "tab" ) ) Tabs _CloseTabs ( [ parseInt ( TabNode . id ) ] ) ;
}
if ( bgOption == "undo_close_tab" ) {
chrome . sessions . getRecentlyClosed ( null , function ( sessions ) {
if ( sessions . length > 0 ) chrome . sessions . restore ( null , function ( restored ) { } ) ;
} ) ;
}
if ( bgOption == "reload_tab" ) { chrome . tabs . reload ( parseInt ( TabNode . id ) ) ; }
if ( bgOption == "unload_tab" ) {
if ( TabNode . classList . contains ( "active_tab" ) ) {
Tabs _SwitchActiveTabBeforeClose ( tt . active _group ) ;
setTimeout ( function ( ) { Tabs _DiscardTabs ( [ parseInt ( TabNode . id ) ] ) ; } , 500 ) ;
} else {
Tabs _DiscardTabs ( [ parseInt ( TabNode . id ) ] ) ;
}
}
if ( bgOption == "activate_previous_active" && TabNode . classList . contains ( "active_tab" ) ) {
let PrevActiveTabId = parseInt ( tt . groups [ tt . active _group ] . prev _active _tab ) ;
if ( isNaN ( PrevActiveTabId ) == false ) chrome . tabs . update ( PrevActiveTabId , { active : true } ) ;
}
2018-05-22 02:11:29 +02:00
}
2018-12-13 23:55:34 +01:00
function Tabs _SetActiveTab ( tabId , switchToGroup ) {
if ( opt . debug ) Utils _log ( "f: SetActiveTab, tabId: " + tabId ) ;
let Tab = document . getElementById ( tabId ) ;
if ( Tab != null ) {
let TabGroup = DOM _GetParentsByClass ( Tab , "group" ) ;
if ( TabGroup . length ) {
if ( Tab . classList . contains ( "tab" ) ) Groups _SetActiveTabInGroup ( TabGroup [ 0 ] . id , tabId ) ;
if ( switchToGroup ) Groups _SetActiveGroup ( TabGroup [ 0 ] . id , false , false ) ; // not going to scroll, because mostly it's going to change to a new active in group AFTER switch, so we are not going to scroll to previous active tab
}
// let selected = document.querySelectorAll(".selected");
// for (let s of selected) {
// s.classList.remove("selected");
// }
// let selected_not_in_group = document.querySelectorAll(".pin, #" + tt.active_group + " .tab");
// for (let s of selected_not_in_group) {
// DOM_SetClasses(s, [], ["active_tab", "selected", "selected_last", "selected_frozen", "selected_temporarly", "tab_header_hover"], []);
// }
let active _tabs = document . querySelectorAll ( ".pin.active_tab, #" + tt . active _group + " .active_tab" ) ;
for ( let s of active _tabs ) {
DOM _SetClasses ( s , [ ] , [ "active_tab" ] , [ ] ) ;
}
DOM _RemoveHighlight ( ) ;
DOM _SetClasses ( Tab , [ "active_tab" ] , [ "attention" ] , [ ] ) ;
if ( tt . tabs [ tabId ] ) tt . tabs [ tabId ] . ScrollToTab ( ) ;
}
2018-03-13 14:39:34 +01:00
}
2018-12-13 23:55:34 +01:00
function Tabs _SwitchActiveTabBeforeClose ( ActiveGroupId ) {
if ( opt . debug ) Utils _log ( "f: SwitchActiveTabBeforeClose" ) ;
let activeGroup = document . getElementById ( ActiveGroupId ) ;
if ( document . querySelectorAll ( "#" + ActiveGroupId + " .tab:not(.will_be_closed)" ) . length <= 1 && document . querySelector ( ".pin.active_tab" ) == null ) { // CHECK IF CLOSING LAST TAB IN ACTIVE GROUP
let pins = document . querySelectorAll ( ".pin" ) ;
if ( pins . length > 0 ) { // IF THERE ARE ANY PINNED TABS, ACTIVATE IT
if ( opt . debug ) Utils _log ( "available pin, switching to: " + pins [ pins . length - 1 ] . id ) ;
chrome . tabs . update ( parseInt ( pins [ pins . length - 1 ] . id ) , { active : true } ) ;
return ;
} else { // NO OTHER CHOICE BUT TO SEEK IN ANOTHER GROUP
if ( opt . after _closing _active _tab == "above" || opt . after _closing _active _tab == "above_seek_in_parent" ) {
if ( activeGroup . previousSibling != null ) {
if ( document . querySelectorAll ( "#" + activeGroup . previousSibling . id + " .tab" ) . length > 0 ) {
Groups _SetActiveGroup ( activeGroup . previousSibling . id , true , true ) ;
} else {
Tabs _SwitchActiveTabBeforeClose ( activeGroup . previousSibling . id ) ;
return ;
}
} else {
Groups _SetActiveGroup ( "tab_list" , true , true ) ;
}
} else {
if ( activeGroup . nextSibling != null ) {
if ( document . querySelectorAll ( "#" + activeGroup . nextSibling . id + " .tab" ) . length > 0 ) {
Groups _SetActiveGroup ( activeGroup . nextSibling . id , true , true ) ;
} else {
Tabs _SwitchActiveTabBeforeClose ( activeGroup . nextSibling . id ) ;
return ;
}
} else {
Groups _SetActiveGroup ( "tab_list" , true , true ) ;
}
}
}
} else {
if ( opt . debug ) Utils _log ( "available tabs in current group, switching option is: " + opt . after _closing _active _tab ) ;
if ( opt . after _closing _active _tab == "above" ) Tabs _ActivatePrevTab ( true ) ;
if ( opt . after _closing _active _tab == "below" ) Tabs _ActivateNextTab ( true ) ;
if ( opt . after _closing _active _tab == "above_seek_in_parent" ) Tabs _ActivatePrevTabSameLevel ( ) ;
if ( opt . after _closing _active _tab == "below_seek_in_parent" ) Tabs _ActivateNextTabSameLevel ( ) ;
}
2018-03-13 14:39:34 +01:00
}
2018-12-13 23:55:34 +01:00
function Tabs _ActivateNextTabSameLevel ( ) {
let activeTab = document . querySelector ( "#" + tt . active _group + " .tab.active_tab" ) != null ? document . querySelector ( "#" + tt . active _group + " .tab.active_tab" ) : document . querySelector ( ".pin.active_tab" ) ;
if ( activeTab == null ) return ;
let NewActiveId ;
let Node = activeTab ;
if ( activeTab . classList . contains ( "tab" ) ) {
if ( opt . promote _children && activeTab . childNodes [ 1 ] . firstChild != null && activeTab . childNodes [ 1 ] . firstChild . classList . contains ( "tab" ) && activeTab . childNodes [ 1 ] . firstChild . classList . contains ( "will_be_closed" ) == false ) NewActiveId = activeTab . childNodes [ 1 ] . firstChild . id ;
}
if ( NewActiveId == undefined ) {
while ( NewActiveId == undefined && Node . nextSibling != null && Node . classList != undefined ) {
if ( ( Node . nextSibling . classList . contains ( "pin" ) || Node . nextSibling . classList . contains ( "tab" ) ) && Node . nextSibling . classList . contains ( "will_be_closed" ) == false ) NewActiveId = Node . nextSibling . id ;
Node = Node . nextSibling ;
}
}
if ( NewActiveId == undefined ) {
while ( NewActiveId == undefined && Node . previousSibling != null && Node . classList != undefined ) {
if ( ( Node . previousSibling . classList . contains ( "pin" ) || Node . previousSibling . classList . contains ( "tab" ) ) && Node . previousSibling . classList . contains ( "will_be_closed" ) == false ) NewActiveId = Node . previousSibling . id ;
Node = Node . previousSibling ;
}
}
if ( NewActiveId == undefined ) { Tabs _ActivatePrevTab ( ) ; }
if ( NewActiveId != undefined ) {
let tabId = parseInt ( NewActiveId ) ;
if ( isNaN ( tabId ) == false ) chrome . tabs . update ( tabId , { active : true } ) ;
}
2018-03-13 14:39:34 +01:00
}
2018-12-13 23:55:34 +01:00
function Tabs _ActivatePrevTabSameLevel ( ) {
let activeTab = document . querySelector ( "#" + tt . active _group + " .tab.active_tab" ) != null ? document . querySelector ( "#" + tt . active _group + " .tab.active_tab" ) : document . querySelector ( ".pin.active_tab" ) ;
if ( activeTab == null ) return ;
let NewActiveId ;
let Node = activeTab ;
if ( activeTab . classList . contains ( "tab" ) ) {
if ( opt . promote _children && activeTab . childNodes [ 1 ] . firstChild != null && activeTab . childNodes [ 1 ] . firstChild . classList . contains ( "tab" ) && activeTab . childNodes [ 1 ] . firstChild . classList . contains ( "will_be_closed" ) == false ) NewActiveId = activeTab . childNodes [ 1 ] . firstChild . id ;
}
if ( NewActiveId == undefined ) {
while ( NewActiveId == undefined && Node . previousSibling != null && Node . classList != undefined ) {
if ( ( Node . previousSibling . classList . contains ( "pin" ) || Node . previousSibling . classList . contains ( "tab" ) ) && Node . previousSibling . classList . contains ( "will_be_closed" ) == false ) NewActiveId = Node . previousSibling . id ;
Node = Node . previousSibling ;
}
}
if ( NewActiveId == undefined ) {
while ( NewActiveId == undefined && Node . nextSibling != null && Node . classList != undefined ) {
if ( ( Node . nextSibling . classList . contains ( "pin" ) || Node . nextSibling . classList . contains ( "tab" ) ) && Node . nextSibling . classList . contains ( "will_be_closed" ) == false ) NewActiveId = Node . nextSibling . id ;
Node = Node . nextSibling ;
}
}
if ( NewActiveId == undefined ) Tabs _ActivateNextTab ( ) ;
if ( NewActiveId != undefined ) {
let tabId = parseInt ( NewActiveId ) ;
if ( isNaN ( tabId ) == false ) chrome . tabs . update ( tabId , { active : true } ) ;
}
2018-03-13 14:39:34 +01:00
}
2018-05-22 02:11:29 +02:00
2018-12-13 23:55:34 +01:00
function Tabs _ActivateNextTab ( allow _loop ) {
let activeTab = document . querySelector ( "#" + tt . active _group + " .tab.active_tab" ) != null ? document . querySelector ( "#" + tt . active _group + " .tab.active_tab" ) : document . querySelector ( ".pin.active_tab" ) ;
if ( activeTab == null ) return ;
let NewActiveId ;
let Node = activeTab ;
let parents = DOM _GetAllParents ( activeTab ) ;
while ( Node != null && Node . classList != undefined ) {
if ( parents . indexOf ( Node ) == - 1 && Node != activeTab && ( Node . classList . contains ( "pin" ) || Node . classList . contains ( "tab" ) ) && Node . classList . contains ( "will_be_closed" ) == false ) {
NewActiveId = Node . id ;
Node = null ;
} else {
if ( parents . indexOf ( Node ) == - 1 && Node . childNodes [ 1 ] && Node . childNodes [ 1 ] . classList . contains ( "children" ) && Node . childNodes [ 1 ] . childNodes . length > 0 && Node . classList . contains ( "c" ) == false ) { // GO TO CHILDREN
Node = Node . childNodes [ 1 ] . firstChild ;
} else {
if ( Node . nextSibling ) { // GO TO NEXT SIBLING
Node = Node . nextSibling ;
} else { // GO UP TO PARENT
Node = Node . parentNode . parentNode ;
}
}
}
}
if ( allow _loop && NewActiveId == undefined ) {
let RestartLoopFromPin = document . querySelector ( ".pin" ) ;
let RestartLoopFromTab = document . querySelector ( "#°" + tt . active _group + " .tab" ) ;
if ( activeTab . classList . contains ( "pin" ) ) {
if ( RestartLoopFromTab != null ) {
NewActiveId = RestartLoopFromTab . id ;
} else {
if ( RestartLoopFromPin != null ) NewActiveId = RestartLoopFromPin . id ;
}
}
if ( activeTab . classList . contains ( "tab" ) ) {
if ( RestartLoopFromPin != null ) {
NewActiveId = RestartLoopFromPin . id ;
} else {
if ( RestartLoopFromTab != null ) NewActiveId = RestartLoopFromTab . id ;
}
}
}
if ( NewActiveId != undefined ) {
let tabId = parseInt ( NewActiveId ) ;
if ( isNaN ( tabId ) == false ) chrome . tabs . update ( tabId , { active : true } ) ;
}
2018-05-22 02:11:29 +02:00
}
2018-12-13 23:55:34 +01:00
function Tabs _ActivatePrevTab ( allow _loop ) {
let activeTab = document . querySelector ( "#" + tt . active _group + " .tab.active_tab" ) != null ? document . querySelector ( "#" + tt . active _group + " .tab.active_tab" ) : document . querySelector ( ".pin.active_tab" ) ;
if ( activeTab == null ) return ;
let NewActiveId ;
let Node = activeTab ;
while ( Node != null && Node . classList != undefined ) {
if ( Node != activeTab && ( Node . classList . contains ( "pin" ) || Node . classList . contains ( "tab" ) ) && Node . classList . contains ( "will_be_closed" ) == false ) {
NewActiveId = Node . id ;
Node = null ;
} else {
if ( Node . previousSibling ) { // GO TO PREV SIBLING
Node = Node . previousSibling ;
while ( Node != null && Node . classList != undefined && Node . childNodes [ 1 ] && Node . childNodes [ 1 ] . classList . contains ( "children" ) && Node . childNodes [ 1 ] . childNodes . length > 0 && Node . classList . contains ( "c" ) == false ) {
Node = Node . childNodes [ 1 ] . lastChild ;
}
} else { // GO UP TO PARENT
Node = Node . parentNode . parentNode ;
}
}
}
if ( allow _loop && NewActiveId == undefined ) {
let RestartLoopFromPin = document . querySelector ( ".pin:last-child" ) ;
let RestartLoopFromTab = document . querySelectorAll ( "#°" + tt . active _group + " .tab" ) ;
if ( activeTab . classList . contains ( "pin" ) ) {
if ( RestartLoopFromTab . length > 0 ) {
NewActiveId = RestartLoopFromTab [ RestartLoopFromTab . length - 1 ] . id ;
} else {
if ( RestartLoopFromPin != null ) NewActiveId = RestartLoopFromPin . id ;
}
}
if ( activeTab . classList . contains ( "tab" ) ) {
if ( RestartLoopFromPin != null ) {
NewActiveId = RestartLoopFromPin . id ;
} else {
if ( RestartLoopFromTab != null ) NewActiveId = RestartLoopFromTab [ RestartLoopFromTab . length - 1 ] . id ;
}
}
}
if ( NewActiveId != undefined ) {
let tabId = parseInt ( NewActiveId ) ;
if ( isNaN ( tabId ) == false ) chrome . tabs . update ( tabId , { active : true } ) ;
}
2018-05-22 02:11:29 +02:00
}