2017-11-12 22:00:40 +01:00
// Copyright (c) 2017 kroppy. All rights reserved.
// Use of this source code is governed by a Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0) license
// that can be found at https://creativecommons.org/licenses/by-nc-nd/4.0/
2017-07-26 22:23:39 +02:00
// ********** TABS FUNCTIONS ***************
2018-05-22 02:11:29 +02:00
2017-11-12 22:00:40 +01:00
async function UpdateData ( ) {
2018-05-22 02:11:29 +02:00
if ( opt . debug ) {
log ( "f: UpdateData" ) ;
}
2017-11-20 18:14:07 +01:00
setInterval ( function ( ) {
2018-01-01 19:50:56 +01:00
if ( schedule _update _data > 1 ) {
schedule _update _data = 1 ;
}
2017-11-12 22:00:40 +01:00
if ( schedule _update _data > 0 ) {
2018-05-22 02:11:29 +02:00
let PinInd = 0 ;
2018-03-13 14:39:34 +01:00
let pins _data = [ ] ;
document . querySelectorAll ( ".pin" ) . forEach ( function ( pin ) {
2018-05-22 02:11:29 +02:00
pins _data . push ( { id : pin . id , index : PinInd } ) ;
PinInd ++ ;
2017-11-12 22:00:40 +01:00
} ) ;
2018-05-22 02:11:29 +02:00
2018-03-13 14:39:34 +01:00
let tabs _data = [ ] ;
document . querySelectorAll ( ".tab" ) . forEach ( function ( tab ) {
tabs _data . push ( { id : tab . id , parent : tab . parentNode . parentNode . id , index : Array . from ( tab . parentNode . children ) . indexOf ( tab ) , expand : ( tab . classList . contains ( "c" ) ? "c" : ( tab . classList . contains ( "o" ) ? "o" : "" ) ) } ) ;
2017-07-26 22:23:39 +02:00
} ) ;
2018-03-13 14:39:34 +01:00
chrome . runtime . sendMessage ( { command : "update_all_tabs" , pins : pins _data , tabs : tabs _data } ) ;
2017-07-26 22:23:39 +02:00
schedule _update _data -- ;
}
2018-05-22 02:11:29 +02:00
} , 2000 ) ;
2017-11-12 22:00:40 +01:00
}
2018-03-13 14:39:34 +01:00
2018-01-01 19:50:56 +01:00
function RearrangeBrowserTabs ( ) {
2018-05-22 02:11:29 +02:00
if ( opt . debug ) {
log ( "f: RearrangeBrowserTabs" ) ;
}
2017-11-20 18:14:07 +01:00
setInterval ( function ( ) {
2018-01-01 19:50:56 +01:00
if ( schedule _rearrange _tabs > 0 ) {
schedule _rearrange _tabs -- ;
2018-03-13 14:39:34 +01:00
let tabIds = Array . prototype . map . call ( document . querySelectorAll ( ".pin, .tab" ) , function ( s ) {
return parseInt ( s . id ) ;
} ) ;
2018-01-01 19:50:56 +01:00
RearrangeBrowserTabsLoop ( tabIds , tabIds . length - 1 ) ;
2017-11-12 22:00:40 +01:00
}
2017-11-20 18:14:07 +01:00
} , 1000 ) ;
2017-11-12 22:00:40 +01:00
}
2018-03-13 14:39:34 +01:00
2018-01-01 19:50:56 +01:00
async function RearrangeBrowserTabsLoop ( tabIds , tabIndex ) {
2018-05-22 02:11:29 +02:00
if ( opt . debug ) {
log ( "f: RearrangeBrowserTabsLoop" ) ;
}
2018-01-01 19:50:56 +01:00
if ( tabIndex >= 0 && schedule _rearrange _tabs == 0 ) {
2018-03-13 14:39:34 +01:00
chrome . tabs . get ( tabIds [ tabIndex ] , function ( tab ) {
if ( tab && tabIndex != tab . index ) {
2017-11-12 22:00:40 +01:00
chrome . tabs . move ( tabIds [ tabIndex ] , { index : tabIndex } ) ;
}
2018-01-01 19:50:56 +01:00
RearrangeBrowserTabsLoop ( tabIds , ( tabIndex - 1 ) ) ;
2017-11-12 22:00:40 +01:00
} ) ;
}
2017-07-26 22:23:39 +02:00
}
2018-03-13 14:39:34 +01:00
2018-01-01 19:50:56 +01:00
function RearrangeTreeTabs ( tabs , bgtabs , first _loop ) {
2017-11-12 22:00:40 +01:00
tabs . forEach ( function ( Tab ) {
2018-03-13 14:39:34 +01:00
let t = document . getElementById ( Tab . id ) ;
if ( bgtabs [ Tab . id ] && t != null && t . parentNode . childNodes [ bgtabs [ Tab . id ] . index ] ) {
let tInd = Array . from ( t . parentNode . children ) . indexOf ( t ) ;
if ( tInd > bgtabs [ Tab . id ] . index ) {
2018-05-22 02:11:29 +02:00
InsterBeforeNode ( t , t . parentNode . childNodes [ bgtabs [ Tab . id ] . index ] ) ;
2017-11-12 22:00:40 +01:00
} else {
2018-05-22 02:11:29 +02:00
InsterAfterNode ( t , t . parentNode . childNodes [ bgtabs [ Tab . id ] . index ] ) ;
2018-03-13 14:39:34 +01:00
}
let newtInd = Array . from ( t . parentNode . children ) . indexOf ( t ) ;
if ( bgtabs [ Tab . id ] && newtInd != bgtabs [ Tab . id ] . index && first _loop ) {
RearrangeTreeTabs ( tabs , bgtabs , false ) ;
2017-11-12 22:00:40 +01:00
}
}
} ) ;
}
2018-03-13 14:39:34 +01:00
function AppendTab ( tab , ParentId , InsertBeforeId , InsertAfterId , Append , Index , SetEvents , AdditionalClass , SkipSetActive , Scroll , addCounter ) {
if ( document . getElementById ( tab . id ) != null ) {
GetFaviconAndTitle ( tab . id , addCounter ) ;
2017-07-26 22:23:39 +02:00
return ;
}
2018-03-13 14:39:34 +01:00
var ClassList = tab . pinned ? "pin" : "tab" ;
if ( tab . discarded ) {
2017-11-12 22:00:40 +01:00
ClassList = ClassList + " discarded" ;
}
2018-03-13 14:39:34 +01:00
if ( AdditionalClass != false ) {
ClassList = ClassList + " " + AdditionalClass ;
}
var tb = document . createElement ( "div" ) ; tb . className = ClassList ; tb . id = tab . id ; // TAB
var th = document . createElement ( "div" ) ; th . className = ( opt . always _show _close && ! opt . never _show _close ) ? "tab_header close_show" : "tab_header" ; th . id = "tab_header" + tab . id ; if ( SetEvents ) { th . draggable = true ; } tb . appendChild ( th ) ; // HEADER
var ex = document . createElement ( "div" ) ; ex . className = "expand" ; ex . id = "exp" + tab . id ; th . appendChild ( ex ) ; // EXPAND ARROW
var tt = document . createElement ( "div" ) ; tt . className = "tab_title" ; tt . id = "tab_title" + tab . id ; th . appendChild ( tt ) ; // TITLE
2017-11-12 22:00:40 +01:00
if ( ! opt . never _show _close ) {
2018-03-13 14:39:34 +01:00
var cl = document . createElement ( "div" ) ; cl . className = "close" ; cl . id = "close" + tab . id ; th . appendChild ( cl ) ; // CLOSE BUTTON
var ci = document . createElement ( "div" ) ; ci . className = "close_img" ; ci . id = "close_img" + tab . id ; cl . appendChild ( ci ) ;
2017-11-12 22:00:40 +01:00
}
2018-03-13 14:39:34 +01:00
var mi = document . createElement ( "div" ) ; mi . className = "tab_mediaicon" ; mi . id = "tab_mediaicon" + tab . id ; th . appendChild ( mi ) ;
var ct = document . createElement ( "div" ) ; ct . className = "children_tabs" ; ct . id = "ct" + tab . id ; tb . appendChild ( ct ) ;
2018-05-22 02:11:29 +02:00
var di = document . createElement ( "div" ) ; di . className = "drag_indicator" ; di . id = "di" + tab . id ; tb . appendChild ( di ) ; // DROP TARGET INDICATOR
2018-03-13 14:39:34 +01:00
if ( SetEvents ) {
2018-05-22 02:11:29 +02:00
ct . onclick = function ( event ) {
if ( event . target == this && event . which == 1 ) {
DeselectFolders ( ) ;
DeselectTabs ( ) ;
}
}
2018-03-13 14:39:34 +01:00
ct . onmousedown = function ( event ) {
if ( event . target == this ) {
if ( event . which == 2 && event . target == this ) {
event . stopImmediatePropagation ( ) ;
ActionClickGroup ( this . parentNode , opt . midclick _group ) ;
}
if ( event . which == 3 ) {
ShowFGlobalMenu ( event ) ;
}
}
}
ct . ondblclick = function ( event ) {
if ( event . target == this ) {
ActionClickGroup ( this . parentNode , opt . dbclick _group ) ;
}
}
ex . onmousedown = function ( event ) {
if ( document . getElementById ( "main_menu" ) . style . top != "-1000px" ) {
HideMenus ( ) ;
}
if ( event . which == 1 && ! event . shiftKey && ! event . ctrlKey ) {
EventExpandBox ( this . parentNode . parentNode ) ;
}
}
ex . onmouseenter = function ( event ) {
this . classList . add ( "hover" ) ;
}
ex . onmouseleave = function ( event ) {
this . classList . remove ( "hover" ) ;
}
if ( ! opt . never _show _close ) {
cl . onmousedown = function ( event ) {
event . stopImmediatePropagation ( ) ;
if ( event . which != 3 ) {
CloseTabs ( [ parseInt ( this . parentNode . parentNode . id ) ] ) ;
}
}
cl . onmouseenter = function ( event ) {
this . classList . add ( "close_hover" ) ;
}
cl . onmouseleave = function ( event ) {
this . classList . remove ( "close_hover" ) ;
}
}
th . onclick = function ( event ) {
event . stopImmediatePropagation ( ) ;
if ( document . getElementById ( "main_menu" ) . style . top != "-1000px" ) {
HideMenus ( ) ;
} else {
2018-05-22 02:11:29 +02:00
if ( event . which == 1 && ! event . shiftKey && ! event . ctrlKey && event . target . classList . contains ( "tab_header" ) ) {
2018-03-13 14:39:34 +01:00
DeselectTabs ( ) ;
chrome . tabs . update ( parseInt ( this . parentNode . id ) , { active : true } ) ;
}
}
}
th . ondblclick = function ( event ) {
2018-05-22 02:11:29 +02:00
if ( event . target . classList && event . target . classList . contains ( "tab_header" ) ) {
2018-03-13 14:39:34 +01:00
ActionClickTab ( this . parentNode , opt . dbclick _tab ) ;
}
}
th . onmousedown = function ( event ) {
2018-05-22 02:11:29 +02:00
if ( browserId == "V" ) {
chrome . windows . getCurrent ( { populate : false } , function ( window ) {
if ( CurrentWindowId != window . id ) {
location . reload ( ) ;
}
} ) ;
}
2018-03-13 14:39:34 +01:00
event . stopImmediatePropagation ( ) ;
if ( event . which == 1 ) {
EventSelectTab ( event , this . parentNode ) ;
}
if ( event . which == 2 ) {
event . preventDefault ( ) ;
ActionClickTab ( this . parentNode , opt . midclick _tab ) ;
}
if ( event . which == 3 ) {
ShowTabMenu ( this . parentNode , event ) ;
}
}
th . 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" ) ;
}
}
th . 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" ) ;
}
}
2018-05-22 02:11:29 +02:00
th . ondragstart = function ( event ) { // DRAG START
TabStartDrag ( this . parentNode , event ) ;
2018-03-13 14:39:34 +01:00
}
2018-05-22 02:11:29 +02:00
2018-03-13 14:39:34 +01:00
th . ondragenter = function ( event ) {
this . classList . remove ( "tab_header_hover" ) ;
2018-05-22 02:11:29 +02:00
DragOverTimer = false ;
2018-03-13 14:39:34 +01:00
setTimeout ( function ( ) {
2018-05-22 02:11:29 +02:00
DragOverTimer = true ;
2018-03-13 14:39:34 +01:00
} , 1000 ) ;
}
2018-05-22 02:11:29 +02:00
th . ondragleave = function ( event ) {
RemoveHighlight ( ) ;
2018-03-13 14:39:34 +01:00
}
2018-05-22 02:11:29 +02:00
th . ondragover = function ( event ) {
TabDragOver ( this , event ) ;
2018-03-13 14:39:34 +01:00
}
mi . 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 ( tab . pinned ) {
parent = document . getElementById ( "pin_list" ) ;
2017-11-12 22:00:40 +01:00
} else {
2018-03-13 14:39:34 +01:00
if ( ParentId == false || ParentId == undefined || document . getElementById ( ParentId ) == null || document . querySelector ( ".pin[id='" + ParentId + "']" ) != null || ParentId == "pin_list" ) {
parent = document . getElementById ( "ct" + active _group ) ;
2017-11-12 22:00:40 +01:00
} else {
2018-03-13 14:39:34 +01:00
parent = document . getElementById ( "ct" + ParentId ) ;
if ( parent . children . length == 0 ) {
parent . parentNode . classList . add ( "o" ) ;
parent . parentNode . classList . remove ( "c" ) ;
2017-11-12 22:00:40 +01:00
}
2017-07-26 22:23:39 +02:00
}
2017-11-12 22:00:40 +01:00
}
2018-03-13 14:39:34 +01:00
if ( Append && parent ) {
parent . appendChild ( tb ) ;
2017-11-12 22:00:40 +01:00
}
2018-03-13 14:39:34 +01:00
if ( ! Append && parent ) {
parent . prepend ( tb ) ;
2017-11-12 22:00:40 +01:00
}
2018-03-13 14:39:34 +01:00
if ( InsertBeforeId ) {
let Before = document . getElementById ( InsertBeforeId ) ;
if ( Before != null ) {
if ( ( tab . pinned && Before . classList . contains ( "pin" ) ) || ( tab . pinned == false && Before . classList . contains ( "tab" ) ) ) {
Before . parentNode . insertBefore ( tb , Before ) ;
}
2017-07-26 22:23:39 +02:00
}
}
2018-03-13 14:39:34 +01:00
if ( InsertAfterId ) {
let After = document . getElementById ( InsertAfterId ) ;
if ( After != null ) {
if ( ( tab . pinned && After . classList . contains ( "pin" ) ) || ( tab . pinned == false && After . classList . contains ( "tab" ) ) ) {
2018-05-22 02:11:29 +02:00
InsterAfterNode ( tb , After ) ;
2018-03-13 14:39:34 +01:00
}
2017-07-26 22:23:39 +02:00
}
}
2018-03-13 14:39:34 +01:00
if ( Index ) {
if ( tb . parentNode . childNodes . length >= Index ) {
tb . parentNode . insertBefore ( tb , tb . parentNode . childNodes [ Index ] ) ;
} else {
tb . parentNode . appendChild ( tb ) ;
}
2017-07-26 22:23:39 +02:00
}
2018-03-13 14:39:34 +01:00
GetFaviconAndTitle ( tab . id , addCounter ) ;
RefreshMediaIcon ( tab . id ) ;
if ( tab . active && SkipSetActive == false ) {
SetActiveTab ( tab . id ) ;
}
if ( Scroll ) {
ScrollToTab ( tab . id ) ;
2017-07-26 22:23:39 +02:00
}
}
2018-03-13 14:39:34 +01:00
2017-11-12 22:00:40 +01:00
function RemoveTabFromList ( tabId ) {
2018-05-22 02:11:29 +02:00
if ( opt . debug ) {
log ( "f: RemoveTabFromList, tabId: " + tabId ) ;
}
2018-03-13 14:39:34 +01:00
let tab = document . getElementById ( tabId ) ;
if ( tab != null ) {
tab . parentNode . removeChild ( tab ) ;
2017-07-26 22:23:39 +02:00
}
}
2018-03-13 14:39:34 +01:00
function SetTabClass ( tabId , pin ) {
let PinList = document . getElementById ( "pin_list" ) ;
let GroupList = document . getElementById ( "ct" + active _group ) ;
let Tab = document . getElementById ( tabId ) ;
if ( Tab != null ) {
if ( pin ) {
if ( Tab . parentNode . id != "pin_list" ) {
document . getElementById ( "pin_list" ) . appendChild ( Tab ) ;
}
Tab . classList . remove ( "tab" ) ;
Tab . classList . remove ( "o" ) ;
Tab . classList . remove ( "c" ) ;
Tab . classList . add ( "pin" ) ;
if ( document . getElementById ( "ct" + tabId ) . childNodes . length > 0 ) { // flatten out children
let tabs = document . querySelectorAll ( "#ct" + tabId + " .pin, #ct" + tabId + " .tab" ) ;
for ( let i = tabs . length - 1 ; i >= 0 ; i -- ) {
tabs [ i ] . remove ( "tab" ) ;
tabs [ i ] . remove ( "o" ) ;
tabs [ i ] . remove ( "c" ) ;
tabs [ i ] . classList . add ( "pin" ) ;
2018-05-22 02:11:29 +02:00
InsterAfterNode ( tabs [ i ] , Tab ) ;
2018-03-13 14:39:34 +01:00
chrome . tabs . update ( parseInt ( tabs [ i ] . id ) , { pinned : true } ) ;
}
}
2018-05-22 02:11:29 +02:00
chrome . tabs . update ( parseInt ( tabId ) , { pinned : true } ) ;
2018-03-13 14:39:34 +01:00
} else {
2018-05-22 02:11:29 +02:00
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 ) ;
}
2018-03-13 14:39:34 +01:00
}
Tab . classList . remove ( "pin" ) ;
Tab . classList . remove ( "attention" ) ;
Tab . classList . add ( "tab" ) ;
RefreshExpandStates ( ) ;
2018-05-22 02:11:29 +02:00
chrome . tabs . update ( parseInt ( tabId ) , { pinned : false } ) ;
2017-07-26 22:23:39 +02:00
}
2018-03-13 14:39:34 +01:00
RefreshGUI ( ) ;
2017-07-26 22:23:39 +02:00
}
}
2018-05-22 02:11:29 +02:00
function SetMultiTabsClass ( TabsIds , pin ) {
TabsIds . forEach ( function ( tabId ) {
SetTabClass ( tabId , pin ) ;
} ) ;
}
2018-03-13 14:39:34 +01:00
2018-05-22 02:11:29 +02:00
function SetActiveTab ( tabId , switchToGroup ) {
if ( opt . debug ) {
log ( "f: SetActiveTab, tabId: " + tabId ) ;
}
2018-03-13 14:39:34 +01:00
let Tab = document . getElementById ( tabId ) ;
if ( Tab != null ) {
2018-05-22 02:11:29 +02:00
let TabGroup = GetParentsByClass ( Tab , "group" ) ;
if ( TabGroup . length ) {
if ( Tab . classList . contains ( "tab" ) ) {
SetActiveTabInGroup ( TabGroup [ 0 ] . id , tabId ) ;
}
if ( switchToGroup ) {
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
}
}
2018-03-13 14:39:34 +01:00
document . querySelectorAll ( ".selected_folder" ) . forEach ( function ( s ) {
s . classList . remove ( "selected_folder" ) ;
} ) ;
2018-05-22 02:11:29 +02:00
// document.querySelectorAll(".pin, #"+active_group+" .tab"+(TabGroup.length ? ", #"+TabGroup[0].id+" .tab" : "")).forEach(function(s){
2018-03-13 14:39:34 +01:00
document . querySelectorAll ( ".pin, #" + active _group + " .tab" ) . forEach ( function ( s ) {
s . classList . remove ( "active_tab" ) ;
s . classList . remove ( "selected_tab" ) ;
s . classList . remove ( "selected_last" ) ;
s . classList . remove ( "selected_frozen" ) ;
s . classList . remove ( "selected_temporarly" ) ;
s . classList . remove ( "tab_header_hover" ) ;
} ) ;
2018-05-22 02:11:29 +02:00
RemoveHighlight ( ) ;
2018-03-13 14:39:34 +01:00
Tab . classList . remove ( "attention" ) ;
Tab . classList . add ( "active_tab" ) ;
2017-07-26 22:23:39 +02:00
ScrollToTab ( tabId ) ;
}
}
2018-03-13 14:39:34 +01:00
2017-11-12 22:00:40 +01:00
function ScrollToTab ( tabId ) {
2018-03-13 14:39:34 +01:00
let Tab = document . getElementById ( tabId ) ;
if ( Tab != null ) {
if ( Tab . classList . contains ( "pin" ) ) {
if ( Tab . getBoundingClientRect ( ) . left - document . getElementById ( "pin_list" ) . getBoundingClientRect ( ) . left < 0 ) {
document . getElementById ( "pin_list" ) . scrollLeft = document . getElementById ( "pin_list" ) . scrollLeft + Tab . getBoundingClientRect ( ) . left - document . getElementById ( "pin_list" ) . getBoundingClientRect ( ) . left - 2 ;
2018-01-01 19:50:56 +01:00
} else {
2018-03-13 14:39:34 +01:00
if ( Tab . getBoundingClientRect ( ) . left - document . getElementById ( "pin_list" ) . getBoundingClientRect ( ) . left > document . getElementById ( active _group ) . getBoundingClientRect ( ) . width - document . querySelector ( ".tab_header" ) . getBoundingClientRect ( ) . width ) {
document . getElementById ( "pin_list" ) . scrollLeft = document . getElementById ( "pin_list" ) . scrollLeft + Tab . getBoundingClientRect ( ) . left - document . getElementById ( "pin_list" ) . getBoundingClientRect ( ) . left - document . getElementById ( "pin_list" ) . getBoundingClientRect ( ) . width + document . querySelector ( ".tab_header" ) . getBoundingClientRect ( ) . width + 2 ;
2018-01-01 19:50:56 +01:00
}
2017-07-26 22:23:39 +02:00
}
}
2018-03-13 14:39:34 +01:00
if ( Tab . classList . contains ( "tab" ) && document . querySelector ( "#" + active _group + " [id='" + tabId + "']" ) != null ) {
let Parents = GetParentsByClass ( Tab , "c" ) ;
if ( Parents . length > 0 ) {
Parents . forEach ( function ( s ) {
s . classList . remove ( "c" ) ;
s . classList . add ( "o" ) ;
} ) ;
}
if ( Tab . getBoundingClientRect ( ) . top - document . getElementById ( active _group ) . getBoundingClientRect ( ) . top < 0 ) {
document . getElementById ( active _group ) . scrollTop = document . getElementById ( active _group ) . scrollTop + Tab . getBoundingClientRect ( ) . top - document . getElementById ( active _group ) . getBoundingClientRect ( ) . top - 2 ;
} else {
if ( Tab . getBoundingClientRect ( ) . top - document . getElementById ( active _group ) . getBoundingClientRect ( ) . top > document . getElementById ( active _group ) . getBoundingClientRect ( ) . height - document . querySelector ( ".tab_header" ) . getBoundingClientRect ( ) . height ) {
document . getElementById ( active _group ) . scrollTop = document . getElementById ( active _group ) . scrollTop + Tab . getBoundingClientRect ( ) . top - document . getElementById ( active _group ) . getBoundingClientRect ( ) . top - document . getElementById ( active _group ) . getBoundingClientRect ( ) . height + document . querySelector ( ".tab_header" ) . getBoundingClientRect ( ) . height + 10 ;
2018-01-01 19:50:56 +01:00
}
2017-07-26 22:23:39 +02:00
}
}
}
}
2018-03-13 14:39:34 +01:00
function Detach ( tabsIds , Folders ) {
2018-05-22 02:11:29 +02:00
if ( opt . debug ) {
log ( "f: Detach" ) ;
}
2017-11-12 22:00:40 +01:00
chrome . windows . get ( CurrentWindowId , { populate : true } , function ( window ) {
2018-03-13 14:39:34 +01:00
if ( window . tabs . length == 1 || tabsIds . length == 0 ) {
return ;
}
if ( tabsIds . length == window . tabs . length ) {
2018-05-22 02:11:29 +02:00
if ( opt . debug ) {
log ( "You are trying to detach all tabs! Skipping!" ) ;
}
2017-07-26 22:23:39 +02:00
return ;
}
2018-05-22 02:11:29 +02:00
let Indexes = [ ] ;
let Parents = [ ] ;
let Expands = [ ] ;
let NewIds = [ ] ; // MOZILLA BUG 1398272
let NewTabs = [ ] ;
let Ind = 0 ;
tabsIds . forEach ( function ( tabId ) {
let tab = document . getElementById ( tabId ) ;
NewIds . push ( tabId ) ; // MOZILLA BUG 1398272
Indexes . push ( Array . from ( tab . parentNode . children ) . indexOf ( tab ) ) ;
Parents . push ( tab . parentNode . parentNode . id ) ;
Expands . push ( ( tab . classList . contains ( "c" ) ? "c" : ( tab . classList . contains ( "o" ) ? "o" : "" ) ) ) ;
} ) ;
2018-03-13 14:39:34 +01:00
chrome . windows . create ( { tabId : tabsIds [ 0 ] , state : window . state } , function ( new _window ) {
2018-01-01 19:50:56 +01:00
tabsIds . forEach ( function ( tabId ) {
chrome . tabs . move ( tabId , { windowId : new _window . id , index : - 1 } , function ( MovedTab ) {
2018-03-13 14:39:34 +01:00
if ( browserId == "F" ) { // MOZILLA BUG 1398272
if ( Ind == 0 ) { // MOZILLA BUG 1398272
NewIds [ Ind ] = new _window . tabs [ 0 ] . id ; // MOZILLA BUG 1398272
} else { // MOZILLA BUG 1398272
NewIds [ Ind ] = MovedTab [ 0 ] . id ; // MOZILLA BUG 1398272
} // MOZILLA BUG 1398272
NewTabs . push ( { id : NewIds [ Ind ] , index : Indexes [ Ind ] , parent : ( ( tabsIds . indexOf ( parseInt ( Parents [ Ind ] ) ) != - 1 ) ? NewIds [ tabsIds . indexOf ( parseInt ( Parents [ Ind ] ) ) ] : Parents [ Ind ] ) , expand : Expands [ Ind ] } ) ; // MOZILLA BUG 1398272
} else { // MOZILLA BUG 1398272
NewTabs . push ( { id : tabsIds [ Ind ] , index : Indexes [ Ind ] , parent : Parents [ Ind ] , expand : Expands [ Ind ] } ) ; // PUSH TAB FROM INDEX
} // MOZILLA BUG 1398272
2018-01-01 19:50:56 +01:00
Ind ++ ;
2018-03-13 14:39:34 +01:00
if ( Ind >= Parents . length - 1 ) {
// chrome.tabs.remove(new_window.tabs[0].id, null);
let Confirmations = 0 ;
let GiveUpLimit = 600 ;
2018-05-22 02:11:29 +02:00
if ( opt . debug ) {
log ( "Detach - Remote Append and Update Loop, waiting for confirmations after attach tabs" ) ;
}
2018-03-13 14:39:34 +01:00
var Append = setInterval ( function ( ) {
chrome . windows . get ( new _window . id , function ( confirm _new _window ) {
chrome . runtime . sendMessage ( { command : "remote_update" , groups : { } , folders : Folders , tabs : NewTabs , windowId : new _window . id } , function ( response ) {
if ( response ) {
Confirmations ++ ;
}
} ) ;
GiveUpLimit -- ;
2018-05-22 02:11:29 +02:00
if ( opt . debug ) {
log ( "Detach -> Attach in new window confirmed: " + Confirmations + " times. If sidebar is not open in new window this loop will give up in: " + GiveUpLimit + " seconds" ) ;
}
2018-03-13 14:39:34 +01:00
if ( Confirmations > 2 || GiveUpLimit < 0 || confirm _new _window == undefined ) {
clearInterval ( Append ) ;
}
} ) ;
} , 1000 ) ;
if ( Folders && Object . keys ( Folders ) . length > 0 ) {
for ( var folder in Folders ) {
RemoveFolder ( Folders [ folder ] . id ) ;
}
}
}
2018-01-01 19:50:56 +01:00
} ) ;
} ) ;
2017-07-26 22:23:39 +02:00
} ) ;
} ) ;
}
2018-03-13 14:39:34 +01:00
2017-11-12 22:00:40 +01:00
function CloseTabs ( tabsIds ) {
2018-05-22 02:11:29 +02:00
if ( opt . debug ) {
log ( "f: CloseTabs, tabsIds are: " + JSON . stringify ( tabsIds ) ) ;
}
tabsIds . forEach ( function ( tabId ) {
let Tab = document . getElementById ( tabId ) ;
if ( Tab != null ) {
Tab . classList . add ( "will_be_closed" ) ;
}
} ) ;
2018-03-13 14:39:34 +01:00
let activeTab = document . querySelector ( ".pin.active_tab, #" + active _group + " .tab.active_tab" ) ;
if ( activeTab != null && tabsIds . indexOf ( parseInt ( activeTab . id ) ) != - 1 ) {
SwitchActiveTabBeforeClose ( active _group ) ;
2018-01-01 19:50:56 +01:00
}
2017-07-26 22:23:39 +02:00
tabsIds . forEach ( function ( tabId ) {
2018-03-13 14:39:34 +01:00
let tab = document . getElementById ( tabId ) ;
if ( tab . classList . contains ( "pin" ) && opt . allow _pin _close ) {
tab . parentNode . removeChild ( tab ) ;
2017-07-26 22:23:39 +02:00
chrome . tabs . update ( tabId , { pinned : false } ) ;
2018-05-22 02:11:29 +02:00
RefreshGUI ( ) ;
2017-07-26 22:23:39 +02:00
}
2018-03-13 14:39:34 +01:00
if ( tabId == tabsIds [ tabsIds . length - 1 ] ) {
setTimeout ( function ( ) {
chrome . tabs . remove ( tabsIds , null ) ;
} , 10 ) ;
}
2017-07-26 22:23:39 +02:00
} ) ;
}
2018-03-13 14:39:34 +01:00
2017-11-12 22:00:40 +01:00
function DiscardTabs ( tabsIds ) {
2018-01-01 19:50:56 +01:00
var delay = 100 ;
2018-03-13 14:39:34 +01:00
let tabNode = document . getElementById ( tabsIds [ 0 ] ) ;
if ( tabNode == null || tabNode . classList . contains ( "discarded" ) || tabNode . classList . contains ( "active_tab" ) ) {
2017-07-26 22:23:39 +02:00
delay = 5 ;
} else {
chrome . tabs . discard ( tabsIds [ 0 ] ) ;
}
tabsIds . splice ( 0 , 1 ) ;
2017-11-12 22:00:40 +01:00
if ( tabsIds . length > 0 ) {
setTimeout ( function ( ) {
2017-07-26 22:23:39 +02:00
DiscardTabs ( tabsIds ) ;
2017-11-20 18:14:07 +01:00
} , delay ) ;
2017-07-26 22:23:39 +02:00
}
}
2018-03-13 14:39:34 +01:00
function SwitchActiveTabBeforeClose ( ActiveGroupId ) {
2018-05-22 02:11:29 +02:00
if ( opt . debug ) {
log ( "f: SwitchActiveTabBeforeClose" ) ;
}
2018-03-13 14:39:34 +01:00
let activeGroup = document . getElementById ( ActiveGroupId ) ;
2018-05-22 02:11:29 +02:00
if ( document . querySelectorAll ( "#" + ActiveGroupId + " .tab" ) . 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 ) {
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 ) {
SetActiveGroup ( activeGroup . previousSibling . id , true , true ) ;
} else {
SwitchActiveTabBeforeClose ( activeGroup . previousSibling . id ) ;
return ;
}
2018-01-01 19:50:56 +01:00
} else {
2018-05-22 02:11:29 +02:00
SetActiveGroup ( "tab_list" , true , true ) ;
2018-01-01 19:50:56 +01:00
}
2018-03-13 14:39:34 +01:00
} else {
2018-05-22 02:11:29 +02:00
if ( activeGroup . nextSibling != null ) {
if ( document . querySelectorAll ( "#" + activeGroup . nextSibling . id + " .tab" ) . length > 0 ) {
SetActiveGroup ( activeGroup . nextSibling . id , true , true ) ;
} else {
SwitchActiveTabBeforeClose ( activeGroup . nextSibling . id ) ;
return ;
}
2018-01-01 19:50:56 +01:00
} else {
2018-05-22 02:11:29 +02:00
SetActiveGroup ( "tab_list" , true , true ) ;
2018-01-01 19:50:56 +01:00
}
}
}
} else {
2018-05-22 02:11:29 +02:00
if ( opt . debug ) {
log ( "available tabs in current group, switching option is: " + opt . after _closing _active _tab ) ;
}
2018-01-01 19:50:56 +01:00
if ( opt . after _closing _active _tab == "above" ) {
2018-03-13 14:39:34 +01:00
ActivatePrevTab ( true ) ;
2018-01-01 19:50:56 +01:00
}
if ( opt . after _closing _active _tab == "below" ) {
2018-03-13 14:39:34 +01:00
ActivateNextTab ( true ) ;
2018-01-01 19:50:56 +01:00
}
if ( opt . after _closing _active _tab == "above_seek_in_parent" ) {
ActivatePrevTabBeforeClose ( ) ;
}
if ( opt . after _closing _active _tab == "below_seek_in_parent" ) {
ActivateNextTabBeforeClose ( ) ;
}
}
}
2018-03-13 14:39:34 +01:00
2018-01-01 19:50:56 +01:00
function ActivateNextTabBeforeClose ( ) {
2018-03-13 14:39:34 +01:00
let activePin = document . querySelector ( ".pin.active_tab" ) ;
if ( activePin != null ) {
if ( activePin . nextSibling != null ) {
chrome . tabs . update ( parseInt ( activePin . nextSibling . id ) , { active : true } ) ;
2017-11-20 18:14:07 +01:00
} else {
2018-03-13 14:39:34 +01:00
if ( activePin . previousSibling != null ) {
chrome . tabs . update ( parseInt ( activePin . previousSibling . id ) , { active : true } ) ;
2017-11-20 18:14:07 +01:00
}
}
2017-07-26 22:23:39 +02:00
}
2018-05-22 02:11:29 +02:00
let will _be _closed = document . querySelectorAll ( "#" + active _group + " .will_be_closed" ) ;
let activeTab = will _be _closed . length > 0 ? will _be _closed [ will _be _closed . length - 1 ] : document . querySelector ( "#" + active _group + " .tab.active_tab" ) ;
if ( activeTab != null && document . querySelectorAll ( "#" + active _group + " .tab:not(.will_be_closed)" ) . length > 1 ) {
if ( opt . promote _children && activeTab . childNodes [ 1 ] . firstChild != null ) {
chrome . tabs . update ( parseInt ( activeTab . childNodes [ 1 ] . firstChild . id ) , { active : true } ) ;
2017-07-26 22:23:39 +02:00
} else {
2018-03-13 14:39:34 +01:00
if ( activeTab . nextSibling != null ) {
chrome . tabs . update ( parseInt ( activeTab . nextSibling . id ) , { active : true } ) ;
2017-07-26 22:23:39 +02:00
} else {
2018-03-13 14:39:34 +01:00
if ( activeTab . previousSibling != null ) {
chrome . tabs . update ( parseInt ( activeTab . previousSibling . id ) , { active : true } ) ;
2017-07-26 22:23:39 +02:00
} else {
2018-03-13 14:39:34 +01:00
if ( activeTab . parentNode . parentNode . classList . contains ( "tab" ) ) {
chrome . tabs . update ( parseInt ( activeTab . parentNode . parentNode . id ) , { active : true } ) ;
2017-11-20 18:14:07 +01:00
} else {
2018-03-13 14:39:34 +01:00
ActivatePrevTab ( ) ;
2017-07-26 22:23:39 +02:00
}
}
}
}
}
}
2018-03-13 14:39:34 +01:00
2018-01-01 19:50:56 +01:00
function ActivatePrevTabBeforeClose ( ) {
2018-03-13 14:39:34 +01:00
let activePin = document . querySelector ( ".pin.active_tab" ) ;
if ( activePin != null ) {
if ( activePin . previousSibling != null ) {
chrome . tabs . update ( parseInt ( activePin . previousSibling . id ) , { active : true } ) ;
2017-11-20 18:14:07 +01:00
} else {
2018-03-13 14:39:34 +01:00
if ( activePin . nextSibling != null ) {
chrome . tabs . update ( parseInt ( activePin . nextSibling . id ) , { active : true } ) ;
2017-11-20 18:14:07 +01:00
}
}
2017-07-26 22:23:39 +02:00
}
2018-05-22 02:11:29 +02:00
let will _be _closed = document . querySelectorAll ( "#" + active _group + " .will_be_closed" ) ;
let activeTab = will _be _closed . length > 0 ? will _be _closed [ 0 ] : document . querySelector ( "#" + active _group + " .tab.active_tab" ) ;
if ( activeTab != null && document . querySelectorAll ( "#" + active _group + " .tab:not(.will_be_closed)" ) . length > 1 ) {
if ( opt . promote _children && activeTab . childNodes [ 1 ] . firstChild != null ) {
chrome . tabs . update ( parseInt ( activeTab . childNodes [ 1 ] . firstChild . id ) , { active : true } ) ;
2017-07-26 22:23:39 +02:00
} else {
2018-03-13 14:39:34 +01:00
if ( activeTab . previousSibling != null ) {
chrome . tabs . update ( parseInt ( activeTab . previousSibling . id ) , { active : true } ) ;
2017-07-26 22:23:39 +02:00
} else {
2018-03-13 14:39:34 +01:00
if ( activeTab . nextSibling != null ) {
chrome . tabs . update ( parseInt ( activeTab . nextSibling . id ) , { active : true } ) ;
2017-11-20 18:14:07 +01:00
} else {
2018-03-13 14:39:34 +01:00
if ( activeTab . parentNode . parentNode . classList . contains ( "tab" ) ) {
chrome . tabs . update ( parseInt ( activeTab . parentNode . parentNode . id ) , { active : true } ) ;
2018-01-01 19:50:56 +01:00
} else {
2018-03-13 14:39:34 +01:00
ActivateNextTab ( ) ;
2017-11-20 18:14:07 +01:00
}
2017-07-26 22:23:39 +02:00
}
}
}
2018-01-01 19:50:56 +01:00
}
2017-07-26 22:23:39 +02:00
}
2018-03-13 14:39:34 +01:00
function ActivateNextTab ( allow _reverse ) {
let activePin = document . querySelector ( ".pin.active_tab" ) ;
if ( activePin != null ) {
if ( activePin . nextSibling != null ) {
chrome . tabs . update ( parseInt ( activePin . nextSibling . id ) , { active : true } ) ;
2018-01-01 19:50:56 +01:00
} else {
2018-03-13 14:39:34 +01:00
if ( activePin . previousSibling != null && allow _reverse ) {
chrome . tabs . update ( parseInt ( activePin . previousSibling . id ) , { active : true } ) ;
2018-01-01 19:50:56 +01:00
}
}
}
2018-05-22 02:11:29 +02:00
let will _be _closed = document . querySelectorAll ( "#" + active _group + " .will_be_closed" ) ;
let activeTab = will _be _closed . length > 0 ? will _be _closed [ will _be _closed . length - 1 ] : document . querySelector ( "#" + active _group + " .tab.active_tab" ) ;
2018-03-13 14:39:34 +01:00
if ( activeTab != null && document . querySelectorAll ( "#" + active _group + " .tab" ) . length > 1 ) {
2018-05-22 02:11:29 +02:00
let FirstChild = activeTab . childNodes [ 1 ] . firstChild ;
2018-03-13 14:39:34 +01:00
if ( FirstChild != null ) {
chrome . tabs . update ( parseInt ( FirstChild . id ) , { active : true } ) ;
2018-01-01 19:50:56 +01:00
} else {
2018-03-13 14:39:34 +01:00
if ( activeTab . nextSibling != null ) {
chrome . tabs . update ( parseInt ( activeTab . nextSibling . id ) , { active : true } ) ;
2018-01-01 19:50:56 +01:00
} else {
2018-03-13 14:39:34 +01:00
let Next = null ;
while ( Next == null && activeTab . parentNode != null && activeTab . parentNode . parentNode != null ) {
if ( activeTab . parentNode . parentNode . classList != undefined && activeTab . parentNode . parentNode . classList . contains ( "tab" ) && activeTab . parentNode . parentNode . nextSibling != null && activeTab . parentNode . parentNode . nextSibling . classList . contains ( "tab" ) ) {
Next = activeTab . parentNode . parentNode . nextSibling ;
}
activeTab = activeTab . parentNode . parentNode ;
}
if ( Next != null ) {
chrome . tabs . update ( parseInt ( Next . id ) , { active : true } ) ;
2018-01-01 19:50:56 +01:00
} else {
2018-03-13 14:39:34 +01:00
if ( allow _reverse ) {
ActivatePrevTab ( ) ;
2018-01-01 19:50:56 +01:00
}
}
}
}
2017-07-26 22:23:39 +02:00
}
}
2018-03-13 14:39:34 +01:00
function ActivatePrevTab ( allow _reverse ) {
let activePin = document . querySelector ( ".pin.active_tab" ) ;
if ( activePin != null ) {
if ( activePin . previousSibling != null ) {
chrome . tabs . update ( parseInt ( activePin . previousSibling . id ) , { active : true } ) ;
2018-01-01 19:50:56 +01:00
} else {
2018-03-13 14:39:34 +01:00
if ( activePin . nextSibling != null && allow _reverse ) {
chrome . tabs . update ( parseInt ( activePin . nextSibling . id ) , { active : true } ) ;
2018-01-01 19:50:56 +01:00
}
}
}
2018-05-22 02:11:29 +02:00
let will _be _closed = document . querySelectorAll ( "#" + active _group + " .will_be_closed" ) ;
let activeTab = will _be _closed . length > 0 ? will _be _closed [ 0 ] : document . querySelector ( "#" + active _group + " .tab.active_tab" ) ;
2018-03-13 14:39:34 +01:00
if ( activeTab != null && document . querySelectorAll ( "#" + active _group + " .tab" ) . length > 1 ) {
let pSchildren = activeTab . previousSibling != null ? document . querySelectorAll ( "#ct" + activeTab . previousSibling . id + " .tab" ) : null ;
if ( activeTab . previousSibling != null && pSchildren . length > 0 ) {
chrome . tabs . update ( parseInt ( pSchildren [ pSchildren . length - 1 ] . id ) , { active : true } ) ;
2018-01-01 19:50:56 +01:00
} else {
2018-03-13 14:39:34 +01:00
if ( activeTab . previousSibling != null ) {
chrome . tabs . update ( parseInt ( activeTab . previousSibling . id ) , { active : true } ) ;
2018-01-01 19:50:56 +01:00
} else {
2018-03-13 14:39:34 +01:00
if ( activeTab . parentNode . parentNode . classList . contains ( "tab" ) ) {
chrome . tabs . update ( parseInt ( activeTab . parentNode . parentNode . id ) , { active : true } ) ;
} else {
if ( allow _reverse ) {
ActivateNextTab ( ) ;
}
2018-01-01 19:50:56 +01:00
}
}
}
2017-07-26 22:23:39 +02:00
}
2017-11-12 22:00:40 +01:00
}
2018-03-13 14:39:34 +01:00
2018-05-22 02:11:29 +02:00
function OpenNewTab ( pin , parentId ) {
if ( pin ) {
chrome . tabs . create ( { pinned : true } , function ( tab ) {
if ( parentId ) {
AppendTab ( tab , "pin_list" , false , parentId , true , false , true , false , false , true , false ) ;
schedule _update _data ++ ;
}
newTabUrl = tab . url ;
} ) ;
} else {
chrome . tabs . create ( { } , function ( tab ) {
if ( parentId ) {
AppendTab ( tab , parentId , false , false , ( opt . append _orphan _tab == "top" ? false : true ) , false , true , false , false , true , false ) ;
schedule _update _data ++ ;
}
newTabUrl = tab . url ;
} ) ;
}
}
function DuplicateTab ( SourceTabNode ) {
chrome . tabs . duplicate ( parseInt ( SourceTabNode . id ) , function ( tab ) {
let DupRetry = setInterval ( function ( ) {
let DupTab = document . getElementById ( tab . id ) ;
if ( DupTab != null ) {
if ( browserId == "F" && tab . pinned ) {
DupTab . classList . remove ( "tab" ) ;
DupTab . classList . add ( "pin" ) ;
}
InsterAfterNode ( DupTab , SourceTabNode ) ;
RefreshExpandStates ( ) ;
schedule _update _data ++ ;
RefreshCounters ( ) ;
clearInterval ( DupRetry ) ;
}
} , 10 ) ;
setTimeout ( function ( ) {
if ( DupRetry ) {
clearInterval ( DupRetry ) ;
}
} , 500 ) ;
} ) ;
}
2018-03-13 14:39:34 +01:00
function DeselectTabs ( ) {
document . querySelectorAll ( ".pin.selected_tab, #" + active _group + " .selected_tab" ) . forEach ( function ( s ) {
s . classList . remove ( "selected_tab" ) ;
s . classList . remove ( "selected_last" ) ;
2017-11-12 22:00:40 +01:00
} ) ;
2018-03-13 14:39:34 +01:00
}
2018-05-22 02:11:29 +02:00
// TAB EVENTS
2018-03-13 14:39:34 +01:00
function EventExpandBox ( Node ) {
if ( Node . classList . contains ( "o" ) ) {
Node . classList . remove ( "o" ) ;
Node . classList . add ( "c" ) ;
if ( Node . classList . contains ( "tab" ) ) {
chrome . runtime . sendMessage ( { command : "update_tab" , tabId : parseInt ( Node . id ) , tab : { expand : "c" } } ) ;
}
if ( Node . classList . contains ( "folder" ) ) {
SaveFolders ( ) ;
}
} else {
if ( Node . classList . contains ( "c" ) ) {
if ( opt . collapse _other _trees ) {
let thisTreeTabs = GetParentsByClass ( Node . childNodes [ 0 ] , "tab" ) ; // start from tab's first child, instead of tab, important to include clicked tab as well
let thisTreeFolders = GetParentsByClass ( Node . childNodes [ 0 ] , "folder" ) ;
document . querySelectorAll ( "#" + active _group + " .o.tab" ) . forEach ( function ( s ) {
s . classList . remove ( "o" ) ;
s . classList . add ( "c" ) ;
chrome . runtime . sendMessage ( { command : "update_tab" , tabId : parseInt ( s . id ) , tab : { expand : "c" } } ) ;
} ) ;
document . querySelectorAll ( "#" + active _group + " .o.folder" ) . forEach ( function ( s ) {
s . classList . remove ( "o" ) ;
s . classList . add ( "c" ) ;
} ) ;
thisTreeTabs . forEach ( function ( s ) {
s . classList . remove ( "c" ) ;
s . classList . add ( "o" ) ;
chrome . runtime . sendMessage ( { command : "update_tab" , tabId : parseInt ( s . id ) , tab : { expand : "o" } } ) ;
} ) ;
thisTreeFolders . forEach ( function ( s ) {
s . classList . remove ( "c" ) ;
s . classList . add ( "o" ) ;
} ) ;
SaveFolders ( ) ;
if ( Node . classList . contains ( "tab" ) ) {
ScrollToTab ( Node . id ) ;
}
2017-11-12 22:00:40 +01:00
} else {
2018-03-13 14:39:34 +01:00
Node . classList . remove ( "c" ) ;
Node . classList . add ( "o" ) ;
if ( Node . classList . contains ( "tab" ) ) {
chrome . runtime . sendMessage ( { command : "update_tab" , tabId : parseInt ( Node . id ) , tab : { expand : "o" } } ) ;
}
if ( Node . classList . contains ( "folder" ) ) {
SaveFolders ( ) ;
2017-11-12 22:00:40 +01:00
}
2018-03-13 14:39:34 +01:00
2017-11-12 22:00:40 +01:00
}
}
2018-03-13 14:39:34 +01:00
}
}
function EventSelectTab ( event , TabNode ) {
DeselectFolders ( ) ;
if ( event . shiftKey ) { // SET SELECTION WITH SHIFT
let activeTab = document . querySelector ( "#" + active _group + " .selected_tab.selected_last" ) ;
if ( activeTab == null ) {
activeTab = document . querySelector ( ".pin.active_tab, #" + active _group + " .tab.active_tab" ) ;
}
if ( activeTab != null && TabNode . parentNode . id == activeTab . parentNode . id ) {
if ( ! event . ctrlKey ) {
document . querySelectorAll ( ".pin.selected_tab, #" + active _group + " .selected_tab" ) . forEach ( function ( s ) {
s . classList . remove ( "selected_frozen" ) ;
s . classList . remove ( "selected_temporarly" ) ;
s . classList . remove ( "selected_tab" ) ;
s . classList . remove ( "selected_last" ) ;
} ) ;
}
let ChildrenArray = Array . from ( TabNode . parentNode . children ) ;
let activeTabIndex = ChildrenArray . indexOf ( activeTab ) ;
let thisTabIndex = ChildrenArray . indexOf ( TabNode ) ;
let fromIndex = thisTabIndex >= activeTabIndex ? activeTabIndex : thisTabIndex ;
let toIndex = thisTabIndex >= activeTabIndex ? thisTabIndex : activeTabIndex ;
for ( let i = fromIndex ; i <= toIndex ; i ++ ) {
activeTab . parentNode . childNodes [ i ] . classList . add ( "selected_tab" ) ;
if ( i == toIndex && event . ctrlKey ) {
activeTab . parentNode . childNodes [ i ] . classList . add ( "selected_last" ) ;
2018-01-01 19:50:56 +01:00
}
2018-03-13 14:39:34 +01:00
}
2017-11-12 22:00:40 +01:00
}
2018-03-13 14:39:34 +01:00
}
if ( event . ctrlKey && ! event . shiftKey ) { // TOGGLE SELECTION WITH CTRL
TabNode . classList . toggle ( "selected_tab" ) ;
if ( TabNode . classList . contains ( "selected_tab" ) ) {
document . querySelectorAll ( ".selected_last" ) . forEach ( function ( s ) {
s . classList . remove ( "selected_last" ) ;
} ) ;
TabNode . classList . add ( "selected_last" ) ;
} else {
TabNode . classList . remove ( "selected_last" ) ;
2017-11-12 22:00:40 +01:00
}
2018-03-13 14:39:34 +01:00
}
}
function ActionClickTab ( TabNode , bgOption ) {
if ( bgOption == "new_tab" ) {
OpenNewTab ( TabNode . classList . contains ( "pin" ) , TabNode . id ) ;
}
if ( bgOption == "expand_collapse" ) {
EventExpandBox ( TabNode ) ;
}
if ( bgOption == "close_tab" ) {
if ( ( TabNode . classList . contains ( "pin" ) && opt . allow _pin _close ) || TabNode . classList . contains ( "tab" ) ) {
CloseTabs ( [ parseInt ( TabNode . id ) ] ) ;
2017-11-12 22:00:40 +01:00
}
2018-03-13 14:39:34 +01:00
}
2018-05-22 02:11:29 +02:00
if ( bgOption == "undo_close_tab" ) {
chrome . sessions . getRecentlyClosed ( null , function ( sessions ) {
if ( sessions . length > 0 ) {
chrome . sessions . restore ( null , function ( restored ) { } ) ;
}
} ) ;
}
2018-03-13 14:39:34 +01:00
if ( bgOption == "reload_tab" ) {
chrome . tabs . reload ( parseInt ( TabNode . id ) ) ;
}
if ( bgOption == "unload_tab" ) {
SwitchActiveTabBeforeClose ( active _group ) ;
DiscardTabs ( [ parseInt ( TabNode . id ) ] ) ;
}
if ( bgOption == "activate_previous_active" && TabNode . classList . contains ( "active_tab" ) ) {
chrome . tabs . update ( parseInt ( bggroups [ active _group ] . prev _active _tab ) , { active : true } ) ;
}
}
2018-05-22 02:11:29 +02:00
function TabStartDrag ( Node , event ) {
event . stopPropagation ( ) ;
event . dataTransfer . setDragImage ( document . getElementById ( "DragImage" ) , 0 , 0 ) ;
event . dataTransfer . setData ( "text" , "" ) ;
event . dataTransfer . setData ( "SourceWindowId" , CurrentWindowId ) ;
CleanUpDragClasses ( ) ;
EmptyDragAndDrop ( ) ;
DragNodeClass = "tab" ;
let TabsIds = [ ] ;
let TabsIdsParents = [ ] ;
let TabsIdsSelected = [ ] ;
if ( Node . classList . contains ( "selected_tab" ) ) {
document . querySelectorAll ( ".group:not(#" + active _group + ") .selected_tab" ) . forEach ( function ( s ) {
s . classList . add ( "selected_frozen" ) ;
s . classList . remove ( "selected_tab" ) ;
s . classList . remove ( "selected_last" ) ;
} ) ;
document . querySelectorAll ( "#pin_list .selected_tab, .group#" + active _group + " .selected_tab" ) . forEach ( function ( s ) {
TabsIdsSelected . push ( parseInt ( s . id ) ) ;
} ) ;
} else {
FreezeSelected ( ) ;
Node . classList . add ( "selected_temporarly" ) ;
Node . classList . add ( "selected_tab" ) ;
TabsIdsSelected . push ( parseInt ( Node . id ) ) ;
}
document . querySelectorAll ( "[id='" + Node . id + "'], [id='" + Node . id + "'] .tab" ) . forEach ( function ( s ) {
s . classList . add ( "dragged_tree" ) ;
} ) ;
if ( opt . max _tree _drag _drop ) {
document . querySelectorAll ( ".dragged_tree .tab" ) . forEach ( function ( s ) {
let parents = GetParentsByClass ( s . parentNode , "dragged_tree" ) ;
if ( parents . length > DragTreeDepth ) {
DragTreeDepth = parents . length ;
}
} ) ;
} else {
DragTreeDepth = - 1 ;
}
// REST OF SELECTED TABS THAT WILL BE DRAGGED
document . querySelectorAll ( ".selected_tab, .selected_tab .tab" ) . forEach ( function ( s ) {
s . classList . add ( "dragged_tree" ) ;
TabsIds . push ( parseInt ( s . id ) ) ;
TabsIdsParents . push ( s . parentNode . id ) ;
} ) ;
DragAndDropData = { TabsIds : TabsIds , TabsIdsParents : TabsIdsParents , TabsIdsSelected : TabsIdsSelected } ;
event . dataTransfer . setData ( "TabsIds" , JSON . stringify ( TabsIds ) ) ;
event . dataTransfer . setData ( "TabsIdsParents" , JSON . stringify ( TabsIdsParents ) ) ;
event . dataTransfer . setData ( "TabsIdsSelected" , JSON . stringify ( TabsIdsSelected ) ) ;
chrome . runtime . sendMessage ( {
command : "drag_drop" ,
DragNodeClass : "tab" ,
DragTreeDepth : DragTreeDepth
} ) ;
}
function TabDragOver ( Node , event ) {
if ( DragNodeClass == "tab" && Node . parentNode . classList . contains ( "dragged_tree" ) == false ) {
if ( Node . parentNode . classList . contains ( "pin" ) ) {
if ( Node . parentNode . classList . contains ( "before" ) == false && event . layerX < Node . clientWidth / 2 ) {
RemoveHighlight ( ) ;
Node . parentNode . classList . remove ( "after" ) ;
Node . parentNode . classList . add ( "before" ) ;
Node . parentNode . classList . add ( "highlighted_drop_target" ) ;
}
if ( Node . parentNode . classList . contains ( "after" ) == false && event . layerX >= Node . clientWidth / 2 ) {
RemoveHighlight ( ) ;
Node . parentNode . classList . remove ( "before" ) ;
Node . parentNode . classList . add ( "after" ) ;
Node . parentNode . classList . add ( "highlighted_drop_target" ) ;
}
}
if ( Node . parentNode . classList . contains ( "tab" ) ) {
let P = ( GetParentsByClass ( Node , "tab" ) ) . length + DragTreeDepth ;
let PGroup = Node . parentNode . parentNode . parentNode . classList . contains ( "group" ) ;
if ( Node . parentNode . classList . contains ( "before" ) == false && event . layerY < Node . clientHeight / 3 && ( P <= opt . max _tree _depth + 1 || opt . max _tree _depth < 0 || PGroup || opt . max _tree _drag _drop == false ) ) {
RemoveHighlight ( ) ;
Node . parentNode . classList . remove ( "inside" ) ;
Node . parentNode . classList . remove ( "after" ) ;
Node . parentNode . classList . add ( "before" ) ;
Node . parentNode . classList . add ( "highlighted_drop_target" ) ;
}
if ( Node . parentNode . classList . contains ( "inside" ) == false && event . layerY > Node . clientHeight / 3 && event . layerY <= 2 * ( Node . clientHeight / 3 ) && ( P <= opt . max _tree _depth || opt . max _tree _depth < 0 || opt . max _tree _drag _drop == false ) ) {
RemoveHighlight ( ) ;
Node . parentNode . classList . remove ( "before" ) ;
Node . parentNode . classList . remove ( "after" ) ;
Node . parentNode . classList . add ( "inside" ) ;
Node . parentNode . classList . add ( "highlighted_drop_target" ) ;
}
if ( Node . parentNode . classList . contains ( "after" ) == false && Node . parentNode . classList . contains ( "o" ) == false && event . layerY > 2 * ( Node . clientHeight / 3 ) && ( P <= opt . max _tree _depth + 1 || opt . max _tree _depth < 0 || PGroup || opt . max _tree _drag _drop == false ) ) {
RemoveHighlight ( ) ;
Node . parentNode . classList . remove ( "inside" ) ;
Node . parentNode . classList . remove ( "before" ) ;
Node . parentNode . classList . add ( "after" ) ;
Node . parentNode . classList . add ( "highlighted_drop_target" ) ;
}
}
}
}