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-07-03 20:36:38 +02:00
if ( tt . schedule _update _data > 1 ) {
tt . schedule _update _data = 1 ;
2018-01-01 19:50:56 +01:00
}
2018-07-03 20:36:38 +02:00
if ( tt . 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 } ) ;
2018-07-03 20:36:38 +02:00
tt . schedule _update _data -- ;
2017-07-26 22:23:39 +02:00
}
2018-07-03 20:36:38 +02:00
} , 1000 ) ;
2017-11-12 22:00:40 +01:00
}
2018-03-13 14:39:34 +01:00
2018-07-03 20:36:38 +02:00
async function RearrangeBrowserTabs ( ) {
2017-11-20 18:14:07 +01:00
setInterval ( function ( ) {
2018-07-03 20:36:38 +02:00
if ( tt . schedule _rearrange _tabs > 0 ) {
tt . schedule _rearrange _tabs -- ;
if ( opt . debug ) {
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 ;
} ) ;
RearrangeBrowserTabsLoop ( ttTabIds , tabIds , ttTabIds . length - 1 ) ;
2018-03-13 14:39:34 +01:00
} ) ;
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-07-03 20:36:38 +02:00
async function RearrangeBrowserTabsLoop ( ttTabIds , tabIds , tabIndex ) {
2018-05-22 02:11:29 +02:00
if ( opt . debug ) {
log ( "f: RearrangeBrowserTabsLoop" ) ;
}
2018-07-03 20:36:38 +02:00
if ( tabIndex >= 0 && tt . schedule _rearrange _tabs == 0 ) {
if ( ttTabIds [ tabIndex ] != tabIds [ tabIndex ] ) {
chrome . tabs . move ( ttTabIds [ tabIndex ] , { index : tabIndex } ) ;
}
setTimeout ( function ( ) {
RearrangeBrowserTabsLoop ( ttTabIds , tabIds , ( tabIndex - 1 ) ) ;
} , 0 ) ;
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-07-03 20:36:38 +02:00
function RearrangeTreeTabs ( bgtabs , show _finish _in _status ) {
if ( opt . debug ) {
log ( "f: RearrangeTreeTabs" ) ;
}
ShowStatusBar ( { show : true , spinner : true , message : "Rearranging tabs and folders" } ) ;
document . querySelectorAll ( ".pin, .tab" ) . forEach ( function ( tab ) {
if ( bgtabs [ tab . id ] ) {
let Sibling = tab . nextElementSibling ;
while ( Sibling ) {
if ( bgtabs [ Sibling . id ] ) {
if ( bgtabs [ tab . id ] . index > bgtabs [ Sibling . id ] . index ) {
InsterAfterNode ( tab , Sibling ) ;
}
}
Sibling = Sibling . nextElementSibling ? Sibling . nextElementSibling : false ;
2017-11-12 22:00:40 +01:00
}
}
2018-07-03 20:36:38 +02:00
if ( show _finish _in _status ) {
ShowStatusBar ( { show : true , spinner : false , message : "Rearranging: done." , hideTimeout : 1000 } ) ;
}
2017-11-12 22:00:40 +01:00
} ) ;
}
2018-03-13 14:39:34 +01:00
2018-07-03 20:36:38 +02:00
function AppendTab ( p ) { // tab: chrome tab object, ParentId: int or string, InsertBeforeId: int or string, InsertAfterId: int or string, Append: bool, SkipSetEvents: bool, AdditionalClass: string, SkipSetActive: bool, Scroll: bool, addCounter: bool, SkipMediaIcon: bool
if ( document . getElementById ( p . tab . id ) != null ) {
GetFaviconAndTitle ( p . tab . id , p . addCounter ) ;
2017-07-26 22:23:39 +02:00
return ;
}
2018-07-03 20:36:38 +02:00
let ClassList = p . tab . pinned ? "pin" : "tab" ;
if ( p . tab . discarded ) {
2017-11-12 22:00:40 +01:00
ClassList = ClassList + " discarded" ;
}
2018-07-03 20:36:38 +02:00
if ( p . AdditionalClass ) {
ClassList = ClassList + " " + p . AdditionalClass ;
2018-03-13 14:39:34 +01:00
}
2018-07-03 20:36:38 +02:00
let tb = document . createElement ( "div" ) ; tb . className = ClassList ; tb . id = p . tab . id ; // TAB
let tbh = document . createElement ( "div" ) ; tbh . className = ( opt . always _show _close && ! opt . never _show _close ) ? "tab_header close_show" : "tab_header" ; tbh . id = "tab_header" + p . tab . id ; if ( ! p . SkipSetEvents ) { tbh . draggable = true ; } tb . appendChild ( tbh ) ; // HEADER
let tbe = document . createElement ( "div" ) ; tbe . className = "expand" ; tbe . id = "exp" + p . tab . id ; tbh . appendChild ( tbe ) ; // EXPAND ARROW
let tbt = document . createElement ( "div" ) ; tbt . className = "tab_title" ; tbt . id = "tab_title" + p . tab . id ; tbh . appendChild ( tbt ) ; // TITLE
let cl = undefined ;
2017-11-12 22:00:40 +01:00
if ( ! opt . never _show _close ) {
2018-07-03 20:36:38 +02:00
cl = document . createElement ( "div" ) ; cl . className = "close" ; cl . id = "close" + p . tab . id ; tbh . appendChild ( cl ) ; // CLOSE BUTTON
let ci = document . createElement ( "div" ) ; ci . className = "close_img" ; ci . id = "close_img" + p . tab . id ; cl . appendChild ( ci ) ;
2017-11-12 22:00:40 +01:00
}
2018-07-03 20:36:38 +02:00
let mi = document . createElement ( "div" ) ; mi . className = "tab_mediaicon" ; mi . id = "tab_mediaicon" + p . tab . id ; tbh . appendChild ( mi ) ;
let ct = document . createElement ( "div" ) ; ct . className = "children_tabs" ; ct . id = "ct" + p . tab . id ; tb . appendChild ( ct ) ;
let di = document . createElement ( "div" ) ; di . className = "drag_indicator" ; di . id = "di" + p . tab . id ; tb . appendChild ( di ) ; // DROP TARGET INDICATOR
2018-03-13 14:39:34 +01:00
2018-07-03 20:36:38 +02:00
if ( ! p . SkipSetEvents ) {
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 ) ;
}
}
2018-07-03 20:36:38 +02:00
tbe . onmousedown = function ( event ) {
2018-03-13 14:39:34 +01:00
if ( document . getElementById ( "main_menu" ) . style . top != "-1000px" ) {
HideMenus ( ) ;
}
if ( event . which == 1 && ! event . shiftKey && ! event . ctrlKey ) {
EventExpandBox ( this . parentNode . parentNode ) ;
}
}
2018-07-03 20:36:38 +02:00
tbe . onmouseenter = function ( event ) {
2018-03-13 14:39:34 +01:00
this . classList . add ( "hover" ) ;
}
2018-07-03 20:36:38 +02:00
tbe . onmouseleave = function ( event ) {
2018-03-13 14:39:34 +01:00
this . classList . remove ( "hover" ) ;
}
2018-07-03 20:36:38 +02:00
if ( ! opt . never _show _close && cl ) {
2018-03-13 14:39:34 +01:00
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" ) ;
}
}
2018-07-03 20:36:38 +02:00
tbh . onclick = function ( event ) {
2018-03-13 14:39:34 +01:00
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 } ) ;
}
}
}
2018-07-03 20:36:38 +02:00
tbh . 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 ) ;
}
}
2018-07-03 20:36:38 +02:00
tbh . onmousedown = function ( event ) {
2018-05-22 02:11:29 +02:00
if ( browserId == "V" ) {
chrome . windows . getCurrent ( { populate : false } , function ( window ) {
2018-07-03 20:36:38 +02:00
if ( tt . CurrentWindowId != window . id && window . focused ) {
2018-05-22 02:11:29 +02:00
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 ) ;
}
}
2018-07-03 20:36:38 +02:00
tbh . onmouseover = function ( event ) {
2018-03-13 14:39:34 +01:00
this . classList . add ( "tab_header_hover" ) ;
if ( opt . never _show _close == false && opt . always _show _close == false ) {
this . classList . add ( "close_show" ) ;
}
}
2018-07-03 20:36:38 +02:00
tbh . onmouseleave = function ( event ) {
2018-03-13 14:39:34 +01:00
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
2018-07-03 20:36:38 +02:00
tbh . ondragstart = function ( event ) { // DRAG START
2018-05-22 02:11:29 +02:00
TabStartDrag ( this . parentNode , event ) ;
2018-03-13 14:39:34 +01:00
}
2018-07-03 20:36:38 +02:00
tbh . ondragenter = function ( event ) {
2018-03-13 14:39:34 +01:00
this . classList . remove ( "tab_header_hover" ) ;
}
2018-07-03 20:36:38 +02:00
tbh . ondragleave = function ( event ) {
2018-05-22 02:11:29 +02:00
RemoveHighlight ( ) ;
2018-03-13 14:39:34 +01:00
}
2018-07-03 20:36:38 +02:00
tbh . ondragover = function ( event ) {
2018-05-22 02:11:29 +02:00
TabDragOver ( this , event ) ;
2018-07-03 20:36:38 +02:00
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 ) {
This . parentNode . classList . add ( "o" ) ;
This . parentNode . classList . remove ( "c" ) ;
}
} , 1500 ) ;
}
}
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 ;
2018-07-03 20:36:38 +02:00
if ( p . tab . pinned ) {
2018-03-13 14:39:34 +01:00
parent = document . getElementById ( "pin_list" ) ;
2017-11-12 22:00:40 +01:00
} else {
2018-07-03 20:36:38 +02:00
if ( p . ParentId == false || p . ParentId == undefined || document . getElementById ( p . ParentId ) == null || document . querySelector ( ".pin[id='" + p . ParentId + "']" ) != null || p . ParentId == "pin_list" ) {
parent = document . getElementById ( "ct" + tt . active _group ) ;
2017-11-12 22:00:40 +01:00
} else {
2018-07-03 20:36:38 +02:00
parent = document . getElementById ( "ct" + p . ParentId ) ;
2018-03-13 14:39:34 +01:00
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-07-03 20:36:38 +02:00
if ( p . Append && parent ) {
2018-03-13 14:39:34 +01:00
parent . appendChild ( tb ) ;
2017-11-12 22:00:40 +01:00
}
2018-07-03 20:36:38 +02:00
if ( ! p . Append && parent ) {
2018-03-13 14:39:34 +01:00
parent . prepend ( tb ) ;
2017-11-12 22:00:40 +01:00
}
2018-03-13 14:39:34 +01:00
2018-07-03 20:36:38 +02:00
if ( p . InsertBeforeId ) {
let Before = document . getElementById ( p . InsertBeforeId ) ;
2018-03-13 14:39:34 +01:00
if ( Before != null ) {
2018-07-03 20:36:38 +02:00
if ( ( p . tab . pinned && Before . classList . contains ( "pin" ) ) || ( p . tab . pinned == false && Before . classList . contains ( "tab" ) ) ) {
2018-03-13 14:39:34 +01:00
Before . parentNode . insertBefore ( tb , Before ) ;
}
2017-07-26 22:23:39 +02:00
}
}
2018-07-03 20:36:38 +02:00
if ( p . InsertAfterId ) {
let After = document . getElementById ( p . InsertAfterId ) ;
2018-03-13 14:39:34 +01:00
if ( After != null ) {
2018-07-03 20:36:38 +02:00
if ( ( p . tab . pinned && After . classList . contains ( "pin" ) ) || ( p . 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-07-03 20:36:38 +02:00
GetFaviconAndTitle ( p . tab . id , p . addCounter ) ;
if ( ! p . SkipMediaIcon ) {
RefreshMediaIcon ( p . tab . id ) ;
2017-07-26 22:23:39 +02:00
}
2018-07-03 20:36:38 +02:00
if ( p . tab . active && ! p . SkipSetActive ) {
SetActiveTab ( p . tab . id ) ;
2018-03-13 14:39:34 +01:00
}
2018-07-03 20:36:38 +02:00
if ( p . Scroll ) {
ScrollToTab ( p . tab . id ) ;
2017-07-26 22:23:39 +02:00
}
2018-07-03 20:36:38 +02:00
return tb ;
2017-07-26 22:23:39 +02:00
}
2018-03-13 14:39:34 +01:00
2018-07-03 20:36:38 +02: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" ) ;
2018-07-03 20:36:38 +02:00
let GroupList = document . getElementById ( "ct" + tt . active _group ) ;
2018-03-13 14:39:34 +01:00
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 -- ) {
2018-07-03 20:36:38 +02:00
tabs [ i ] . classList . remove ( "tab" ) ;
tabs [ i ] . classList . remove ( "o" ) ;
tabs [ i ] . classList . remove ( "c" ) ;
2018-03-13 14:39:34 +01:00
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-07-03 20:36:38 +02:00
chrome . tabs . update ( parseInt ( tabId ) , { pinned : pin } ) ;
2018-05-22 02:11:29 +02:00
} ) ;
}
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-07-03 20:36:38 +02:00
// document.querySelectorAll(".pin, #"+tt.active_group+" .tab"+(TabGroup.length ? ", #"+TabGroup[0].id+" .tab" : "")).forEach(function(s){
document . querySelectorAll ( ".pin, #" + tt . active _group + " .tab" ) . forEach ( function ( s ) {
2018-03-13 14:39:34 +01:00
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-07-03 20:36:38 +02:00
if ( Tab . getBoundingClientRect ( ) . left - document . getElementById ( "pin_list" ) . getBoundingClientRect ( ) . left > document . getElementById ( tt . active _group ) . getBoundingClientRect ( ) . width - document . querySelector ( ".tab_header" ) . getBoundingClientRect ( ) . width ) {
2018-03-13 14:39:34 +01:00
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-07-03 20:36:38 +02:00
if ( Tab . classList . contains ( "tab" ) && document . querySelector ( "#" + tt . active _group + " [id='" + tabId + "']" ) != null ) {
2018-03-13 14:39:34 +01:00
let Parents = GetParentsByClass ( Tab , "c" ) ;
if ( Parents . length > 0 ) {
Parents . forEach ( function ( s ) {
s . classList . remove ( "c" ) ;
s . classList . add ( "o" ) ;
} ) ;
}
2018-07-03 20:36:38 +02:00
if ( Tab . getBoundingClientRect ( ) . top - document . getElementById ( tt . active _group ) . getBoundingClientRect ( ) . top < 0 ) {
document . getElementById ( tt . active _group ) . scrollTop = document . getElementById ( tt . active _group ) . scrollTop + Tab . getBoundingClientRect ( ) . top - document . getElementById ( tt . active _group ) . getBoundingClientRect ( ) . top - 2 ;
2018-03-13 14:39:34 +01:00
} else {
2018-07-03 20:36:38 +02:00
if ( Tab . getBoundingClientRect ( ) . top - document . getElementById ( tt . active _group ) . getBoundingClientRect ( ) . top > document . getElementById ( tt . active _group ) . getBoundingClientRect ( ) . height - document . querySelector ( ".tab_header" ) . getBoundingClientRect ( ) . height ) {
document . getElementById ( tt . active _group ) . scrollTop = document . getElementById ( tt . active _group ) . scrollTop + Tab . getBoundingClientRect ( ) . top - document . getElementById ( tt . active _group ) . getBoundingClientRect ( ) . top - document . getElementById ( tt . 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" ) ;
}
2018-07-03 20:36:38 +02:00
chrome . windows . get ( tt . 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 NewTabs = [ ] ;
let Ind = 0 ;
tabsIds . forEach ( function ( tabId ) {
let tab = document . getElementById ( tabId ) ;
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-07-03 20:36:38 +02:00
tabsIds . splice ( 0 , 1 ) ;
chrome . tabs . move ( tabsIds , { windowId : new _window . id , index : - 1 } , function ( MovedTabs ) {
if ( Folders && Object . keys ( Folders ) . length > 0 ) {
for ( let folder in Folders ) {
RemoveFolder ( Folders [ folder ] . id ) ;
2018-03-13 14:39:34 +01:00
}
2018-07-03 20:36:38 +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
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-07-03 20:36:38 +02:00
let activeTab = document . querySelector ( ".pin.active_tab, #" + tt . active _group + " .tab.active_tab" ) ;
2018-03-13 14:39:34 +01:00
if ( activeTab != null && tabsIds . indexOf ( parseInt ( activeTab . id ) ) != - 1 ) {
2018-07-03 20:36:38 +02:00
SwitchActiveTabBeforeClose ( tt . 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-07-03 20:36:38 +02:00
let 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
2018-07-03 20:36:38 +02:00
let will _be _closed = document . querySelectorAll ( "#" + tt . active _group + " .will_be_closed" ) ;
let activeTab = will _be _closed . length > 0 ? will _be _closed [ will _be _closed . length - 1 ] : document . querySelector ( "#" + tt . active _group + " .tab.active_tab" ) ;
2018-05-22 02:11:29 +02:00
2018-07-03 20:36:38 +02:00
if ( activeTab != null && document . querySelectorAll ( "#" + tt . active _group + " .tab:not(.will_be_closed)" ) . length > 1 ) {
2018-05-22 02:11:29 +02:00
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
2018-07-03 20:36:38 +02:00
let will _be _closed = document . querySelectorAll ( "#" + tt . active _group + " .will_be_closed" ) ;
let activeTab = will _be _closed . length > 0 ? will _be _closed [ 0 ] : document . querySelector ( "#" + tt . active _group + " .tab.active_tab" ) ;
2018-05-22 02:11:29 +02:00
2018-07-03 20:36:38 +02:00
if ( activeTab != null && document . querySelectorAll ( "#" + tt . active _group + " .tab:not(.will_be_closed)" ) . length > 1 ) {
2018-05-22 02:11:29 +02:00
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
2018-07-03 20:36:38 +02:00
let will _be _closed = document . querySelectorAll ( "#" + tt . active _group + " .will_be_closed" ) ;
let activeTab = will _be _closed . length > 0 ? will _be _closed [ will _be _closed . length - 1 ] : document . querySelector ( "#" + tt . active _group + " .tab.active_tab" ) ;
2018-05-22 02:11:29 +02:00
2018-07-03 20:36:38 +02:00
if ( activeTab != null && document . querySelectorAll ( "#" + tt . 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
2018-07-03 20:36:38 +02:00
let will _be _closed = document . querySelectorAll ( "#" + tt . active _group + " .will_be_closed" ) ;
let activeTab = will _be _closed . length > 0 ? will _be _closed [ 0 ] : document . querySelector ( "#" + tt . active _group + " .tab.active_tab" ) ;
2018-05-22 02:11:29 +02:00
2018-07-03 20:36:38 +02:00
if ( activeTab != null && document . querySelectorAll ( "#" + tt . active _group + " .tab" ) . length > 1 ) {
2018-03-13 14:39:34 +01:00
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 ) {
2018-07-03 20:36:38 +02:00
AppendTab ( { tab : tab , ParentId : "pin_list" , InsertAfterId : parentId , Append : true , Scroll : true } ) ;
tt . schedule _update _data ++ ;
2018-05-22 02:11:29 +02:00
}
} ) ;
} else {
chrome . tabs . create ( { } , function ( tab ) {
if ( parentId ) {
2018-07-03 20:36:38 +02:00
AppendTab ( { tab : tab , ParentId : parentId , Append : ( opt . append _orphan _tab == "top" ? false : true ) , Scroll : true } ) ;
tt . schedule _update _data ++ ;
}
if ( opt . move _tabs _on _url _change == "from_empty" ) {
chrome . runtime . sendMessage ( { command : "remove_tab_from_empty_tabs" , tabId : tab . id } ) ;
2018-05-22 02:11:29 +02:00
}
} ) ;
}
}
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 ( ) ;
2018-07-03 20:36:38 +02:00
tt . schedule _update _data ++ ;
2018-05-22 02:11:29 +02:00
RefreshCounters ( ) ;
clearInterval ( DupRetry ) ;
}
} , 10 ) ;
setTimeout ( function ( ) {
if ( DupRetry ) {
clearInterval ( DupRetry ) ;
}
} , 500 ) ;
} ) ;
}
2018-03-13 14:39:34 +01:00
function DeselectTabs ( ) {
2018-07-03 20:36:38 +02:00
document . querySelectorAll ( ".pin.selected_tab, #" + tt . active _group + " .selected_tab" ) . forEach ( function ( s ) {
2018-03-13 14:39:34 +01:00
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" ) ;
2018-07-03 20:36:38 +02:00
document . querySelectorAll ( "#" + tt . active _group + " .o.tab" ) . forEach ( function ( s ) {
2018-03-13 14:39:34 +01:00
s . classList . remove ( "o" ) ;
s . classList . add ( "c" ) ;
chrome . runtime . sendMessage ( { command : "update_tab" , tabId : parseInt ( s . id ) , tab : { expand : "c" } } ) ;
} ) ;
2018-07-03 20:36:38 +02:00
document . querySelectorAll ( "#" + tt . active _group + " .o.folder" ) . forEach ( function ( s ) {
2018-03-13 14:39:34 +01:00
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
2018-07-03 20:36:38 +02:00
let activeTab = document . querySelector ( "#" + tt . active _group + " .selected_tab.selected_last" ) ;
2018-03-13 14:39:34 +01:00
if ( activeTab == null ) {
2018-07-03 20:36:38 +02:00
activeTab = document . querySelector ( ".pin.active_tab, #" + tt . active _group + " .tab.active_tab" ) ;
2018-03-13 14:39:34 +01:00
}
if ( activeTab != null && TabNode . parentNode . id == activeTab . parentNode . id ) {
if ( ! event . ctrlKey ) {
2018-07-03 20:36:38 +02:00
document . querySelectorAll ( ".pin.selected_tab, #" + tt . active _group + " .selected_tab" ) . forEach ( function ( s ) {
2018-03-13 14:39:34 +01:00
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" ) {
2018-07-03 20:36:38 +02:00
if ( TabNode . classList . contains ( "active_tab" ) ) {
SwitchActiveTabBeforeClose ( tt . active _group ) ;
setTimeout ( function ( ) {
DiscardTabs ( [ parseInt ( TabNode . id ) ] ) ;
} , 500 ) ;
} else {
DiscardTabs ( [ parseInt ( TabNode . id ) ] ) ;
}
2018-03-13 14:39:34 +01:00
}
if ( bgOption == "activate_previous_active" && TabNode . classList . contains ( "active_tab" ) ) {
2018-07-03 20:36:38 +02:00
chrome . tabs . update ( parseInt ( tt . groups [ tt . active _group ] . prev _active _tab ) , { active : true } ) ;
2018-03-13 14:39:34 +01:00
}
}
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" , "" ) ;
2018-07-03 20:36:38 +02:00
event . dataTransfer . setData ( "SourceWindowId" , tt . CurrentWindowId ) ;
2018-05-22 02:11:29 +02:00
CleanUpDragClasses ( ) ;
EmptyDragAndDrop ( ) ;
2018-07-03 20:36:38 +02:00
tt . DragNodeClass = "tab" ;
2018-05-22 02:11:29 +02:00
let TabsIds = [ ] ;
let TabsIdsParents = [ ] ;
let TabsIdsSelected = [ ] ;
if ( Node . classList . contains ( "selected_tab" ) ) {
2018-07-03 20:36:38 +02:00
document . querySelectorAll ( ".group:not(#" + tt . active _group + ") .selected_tab" ) . forEach ( function ( s ) {
2018-05-22 02:11:29 +02:00
s . classList . add ( "selected_frozen" ) ;
s . classList . remove ( "selected_tab" ) ;
s . classList . remove ( "selected_last" ) ;
} ) ;
2018-07-03 20:36:38 +02:00
document . querySelectorAll ( "#pin_list .selected_tab, .group#" + tt . active _group + " .selected_tab" ) . forEach ( function ( s ) {
2018-05-22 02:11:29 +02:00
TabsIdsSelected . push ( parseInt ( s . id ) ) ;
} ) ;
} else {
FreezeSelected ( ) ;
Node . classList . add ( "selected_temporarly" ) ;
Node . classList . add ( "selected_tab" ) ;
TabsIdsSelected . push ( parseInt ( Node . id ) ) ;
2018-07-03 20:36:38 +02:00
event . dataTransfer . setData ( "DraggedTabNode" , Node . id ) ;
2018-05-22 02:11:29 +02:00
}
document . querySelectorAll ( "[id='" + Node . id + "'], [id='" + Node . id + "'] .tab" ) . forEach ( function ( s ) {
s . classList . add ( "dragged_tree" ) ;
} ) ;
2018-07-03 20:36:38 +02:00
if ( opt . max _tree _drag _drop || opt . max _tree _depth >= 0 ) {
2018-05-22 02:11:29 +02:00
document . querySelectorAll ( ".dragged_tree .tab" ) . forEach ( function ( s ) {
let parents = GetParentsByClass ( s . parentNode , "dragged_tree" ) ;
2018-07-03 20:36:38 +02:00
if ( parents . length > tt . DragTreeDepth ) {
tt . DragTreeDepth = parents . length ;
2018-05-22 02:11:29 +02:00
}
} ) ;
} else {
2018-07-03 20:36:38 +02:00
tt . DragTreeDepth = - 1 ;
2018-05-22 02:11:29 +02:00
}
// 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 ) ;
} ) ;
2018-07-03 20:36:38 +02:00
let DraggedFolderParents = GetParentsByClass ( Node , "folder" ) ;
DraggedFolderParents . forEach ( function ( s ) {
s . classList . add ( "dragged_parents" ) ;
} ) ;
let DraggedParents = GetParentsByClass ( Node , "tab" ) ;
DraggedParents . forEach ( function ( s ) {
s . classList . add ( "dragged_parents" ) ;
} ) ;
2018-05-22 02:11:29 +02:00
DragAndDropData = { TabsIds : TabsIds , TabsIdsParents : TabsIdsParents , TabsIdsSelected : TabsIdsSelected } ;
2018-07-03 20:36:38 +02:00
event . dataTransfer . setData ( "Class" , "tab" ) ;
2018-05-22 02:11:29 +02:00
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" ,
2018-07-03 20:36:38 +02:00
DragTreeDepth : tt . DragTreeDepth
2018-05-22 02:11:29 +02:00
} ) ;
2018-07-03 20:36:38 +02:00
if ( opt . debug ) {
log ( "f: TabStartDrag, Node: " + Node . id + ", TabsIdsSelected: " + JSON . stringify ( TabsIdsSelected ) + ", TabsIds: " + JSON . stringify ( TabsIds ) + ", TabsIdsParents: " + JSON . stringify ( TabsIdsParents ) ) ;
}
2018-05-22 02:11:29 +02:00
}
function TabDragOver ( Node , event ) {
2018-07-03 20:36:38 +02:00
if ( tt . DragNodeClass == "tab" && Node . parentNode . classList . contains ( "dragged_tree" ) == false ) {
2018-05-22 02:11:29 +02:00
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" ) ) {
2018-07-03 20:36:38 +02:00
let PDepth = ( GetParentsByClass ( Node , "tab" ) ) . length + tt . DragTreeDepth ;
let PIsGroup = Node . parentNode . parentNode . parentNode . classList . contains ( "group" ) ;
let PIsDraggedParents = Node . parentNode . classList . contains ( "dragged_parents" ) ;
if ( Node . parentNode . classList . contains ( "before" ) == false && event . layerY < Node . clientHeight / 3 && ( PDepth <= opt . max _tree _depth + 1 || opt . max _tree _depth < 0 || PIsGroup || PIsDraggedParents || opt . max _tree _drag _drop == false ) ) {
2018-05-22 02:11:29 +02:00
RemoveHighlight ( ) ;
Node . parentNode . classList . remove ( "inside" ) ;
Node . parentNode . classList . remove ( "after" ) ;
Node . parentNode . classList . add ( "before" ) ;
Node . parentNode . classList . add ( "highlighted_drop_target" ) ;
}
2018-07-03 20:36:38 +02:00
if ( Node . parentNode . classList . contains ( "inside" ) == false && event . layerY > Node . clientHeight / 3 && event . layerY <= 2 * ( Node . clientHeight / 3 ) && ( PDepth <= opt . max _tree _depth || opt . max _tree _depth < 0 || PIsDraggedParents || opt . max _tree _drag _drop == false ) ) {
2018-05-22 02:11:29 +02:00
RemoveHighlight ( ) ;
Node . parentNode . classList . remove ( "before" ) ;
Node . parentNode . classList . remove ( "after" ) ;
Node . parentNode . classList . add ( "inside" ) ;
Node . parentNode . classList . add ( "highlighted_drop_target" ) ;
}
2018-07-03 20:36:38 +02:00
if ( Node . parentNode . classList . contains ( "after" ) == false && Node . parentNode . classList . contains ( "o" ) == false && event . layerY > 2 * ( Node . clientHeight / 3 ) && ( PDepth <= opt . max _tree _depth + 1 || opt . max _tree _depth < 0 || PIsGroup || PIsDraggedParents || opt . max _tree _drag _drop == false ) ) {
2018-05-22 02:11:29 +02:00
RemoveHighlight ( ) ;
Node . parentNode . classList . remove ( "inside" ) ;
Node . parentNode . classList . remove ( "before" ) ;
Node . parentNode . classList . add ( "after" ) ;
Node . parentNode . classList . add ( "highlighted_drop_target" ) ;
}
}
}
}