// 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/ // ********** TABS FUNCTIONS *************** async function UpdateData() { setInterval(function() { if (schedule_update_data > 1) { schedule_update_data = 1; } if (schedule_update_data > 0) { if (opt.debug) console.log("function: update tabs"); let pins_data = []; document.querySelectorAll(".pin").forEach(function(pin){ pins_data.push({id: pin.id, index: Array.from(pin.parentNode.children).indexOf(pin)}); }); 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" : ""))}); }); chrome.runtime.sendMessage({command: "update_all_tabs", pins: pins_data, tabs: tabs_data}); schedule_update_data--; } }, 1000); } function RearrangeBrowserTabs() { setInterval(function() { if (schedule_rearrange_tabs > 0) { schedule_rearrange_tabs--; let tabIds = Array.prototype.map.call(document.querySelectorAll(".pin, .tab"), function(s){ return parseInt(s.id); }); RearrangeBrowserTabsLoop(tabIds, tabIds.length-1); } }, 1000); } async function RearrangeBrowserTabsLoop(tabIds, tabIndex) { if (tabIndex >= 0 && schedule_rearrange_tabs == 0){ chrome.tabs.get(tabIds[tabIndex], function(tab) { if (tab && tabIndex != tab.index) { chrome.tabs.move(tabIds[tabIndex], {index: tabIndex}); } RearrangeBrowserTabsLoop( tabIds, (tabIndex-1) ); }); } } function RearrangeTreeTabs(tabs, bgtabs, first_loop) { tabs.forEach(function(Tab) { 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) { t.parentNode.childNodes[bgtabs[Tab.id].index].parentNode.insertBefore(t, t.parentNode.childNodes[bgtabs[Tab.id].index]); } else { if (t.parentNode.childNodes[bgtabs[Tab.id].index].nextSibling != null) { t.parentNode.childNodes[bgtabs[Tab.id].index].parentNode.insertBefore(t, t.parentNode.childNodes[bgtabs[Tab.id].index].nextSibling); } else { t.parentNode.childNodes[bgtabs[Tab.id].index].parentNode.appendChild(t); } } let newtInd = Array.from(t.parentNode.children).indexOf(t); if (bgtabs[Tab.id] && newtInd != bgtabs[Tab.id].index && first_loop) { RearrangeTreeTabs(tabs, bgtabs, false); } } }); } function AppendTab(tab, ParentId, InsertBeforeId, InsertAfterId, Append, Index, SetEvents, AdditionalClass, SkipSetActive, Scroll, addCounter) { if (document.getElementById(tab.id) != null) { GetFaviconAndTitle(tab.id, addCounter); return; } var ClassList = tab.pinned ? "pin" : "tab"; if (tab.discarded) { ClassList = ClassList + " discarded"; } if (AdditionalClass != false) { ClassList = ClassList +" "+ AdditionalClass; } var tb = document.createElement("div"); tb.className = ClassList; tb.id = tab.id; // TAB var dc = document.createElement("div"); dc.className = "drop_target drag_enter_center"; dc.id = "dc"+tab.id; tb.appendChild(dc); // DROP TARGET CENTER var du = document.createElement("div"); du.className = "drop_target drag_entered_top"; du.id = "du"+tab.id; tb.appendChild(du); // DROP TARGET TOP var dd = document.createElement("div"); dd.className = "drop_target drag_entered_bottom"; dd.id = "dd"+tab.id; tb.appendChild(dd); // DROP TARGET BOTTOM 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 if (!opt.never_show_close) { 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); } 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); if (SetEvents) { ct.onmousedown = function(event) { if (event.target == this) { if (event.which == 1) { DeselectFolders(); DeselectTabs(); } 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"); } } tb.ondragenter = function(event) { this.childNodes[1].style.zIndex = 99999; } th.onclick = function(event) { event.stopImmediatePropagation(); if (document.getElementById("main_menu").style.top != "-1000px") { HideMenus(); } else { if (event.which == 1 && !event.shiftKey && !event.ctrlKey && (event.target.classList.contains("tab_title") || event.target.classList.contains("tab_header"))) { DeselectTabs(); // SetActiveTab(this.parentNode.id); chrome.tabs.update(parseInt(this.parentNode.id), { active: true }); } } } th.ondblclick = function(event) { if (event.target.classList && (event.target.classList.contains("tab_title") || event.target.classList.contains("tab_header"))) { ActionClickTab(this.parentNode, opt.dbclick_tab); } } th.onmousedown = function(event) { event.stopImmediatePropagation(); if (event.which == 1) { // SELECT TAB/PIN 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"); } } th.ondragstart = function(event) { // DRAG START event.stopPropagation(); event.dataTransfer.setDragImage(document.getElementById("DragImage"), 0, 0); event.dataTransfer.setData("text", ""); // event.dataTransfer.setData("text/plain", ""); // event.dataTransfer.setData("TTSourceWindowId", CurrentWindowId); CleanUpDragClasses(); EmptyDragAndDrop(); DropTargetsFront(this, true, false); if (this.parentNode.classList.contains("selected_tab") == false) { document.querySelectorAll(".selected_tab").forEach(function(s){ s.classList.add("selected_frozen"); s.classList.remove("selected_tab"); s.classList.remove("selected_last"); }); this.parentNode.classList.add("selected_temporarly"); this.parentNode.classList.add("selected_tab"); } else { 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"); }); } let Tabs = GetSelectedTabs(); document.querySelectorAll("[id='"+this.parentNode.id+"'], [id='"+this.parentNode.id+"'] .folder, [id='"+this.parentNode.id+"'] .tab").forEach(function(s){ s.classList.add("dragged_tree"); }); document.querySelectorAll(".selected_tab, .selected_tab .tab, .selected_folder, .selected_folder .folder").forEach(function(s){ s.classList.add("dragged_selected"); }); if (opt.max_tree_drag_drop) { document.querySelectorAll(".dragged_tree .tab").forEach(function(s){ let parents = GetParentsByClass(s.parentNode, "dragged_tree"); if (parents.length > DragAndDrop.Depth) { DragAndDrop.Depth = parents.length; } }); } else { DragAndDrop.Depth = -1; } DragAndDrop.TabsIds = Object.assign([], Tabs.TabsIds); DragAndDrop.TabsIdsParents = Object.assign([], Tabs.TabsIdsParents); DragAndDrop.TabsIdsSelected = Object.assign([], Tabs.TabsIdsSelected); DragAndDrop.DragNodeClass = "tab"; DragAndDrop.ComesFromWindowId = CurrentWindowId; chrome.runtime.sendMessage({ command: "drag_drop", DragNodeClass: DragAndDrop.DragNodeClass, TabsIds: DragAndDrop.TabsIds, TabsIdsParents: DragAndDrop.TabsIdsParents, TabsIdsSelected: DragAndDrop.TabsIdsSelected, ComesFromWindowId: CurrentWindowId, Depth: DragAndDrop.Depth, Folders: DragAndDrop.Folders, FoldersSelected: DragAndDrop.FoldersSelected }); } th.ondragenter = function(event) { this.classList.remove("tab_header_hover"); } dc.ondragenter = function(event) { DragAndDrop.timeout = false; setTimeout(function() { DragAndDrop.timeout = true; }, 1000); if (DragAndDrop.DragNodeClass == "tab") { HighlightDragEnter(this, 0, "tab"); } } du.ondragenter = function(event) { if (DragAndDrop.DragNodeClass == "tab") { HighlightDragEnter(this, 1, "tab"); } } dd.ondragenter = function(event) { if (DragAndDrop.DragNodeClass == "tab") { HighlightDragEnter(this, 1, "tab"); } } 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"); } else { if (ParentId == false || ParentId == undefined || document.getElementById(ParentId) == null || document.querySelector(".pin[id='"+ParentId+"']") != null || ParentId == "pin_list") { parent = document.getElementById("ct"+active_group); } else { parent = document.getElementById("ct"+ParentId); if (parent.children.length == 0) { parent.parentNode.classList.add("o"); parent.parentNode.classList.remove("c"); } } } if (Append && parent) { parent.appendChild(tb); } if (!Append && parent) { parent.prepend(tb); } 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); } } } if (InsertAfterId) { let After = document.getElementById(InsertAfterId); if (After != null) { if ((tab.pinned && After.classList.contains("pin")) || (tab.pinned == false && After.classList.contains("tab"))) { if (After.nextSibling != null) { After.parentNode.insertBefore(tb, After.nextSibling); } else { After.parentNode.appendChild(tb); } } } } if (Index) { if (tb.parentNode.childNodes.length >= Index) { tb.parentNode.insertBefore(tb, tb.parentNode.childNodes[Index]); } else { tb.parentNode.appendChild(tb); } } GetFaviconAndTitle(tab.id, addCounter); RefreshMediaIcon(tab.id); if (tab.active && SkipSetActive == false) { SetActiveTab(tab.id); } if (Scroll) { ScrollToTab(tab.id); } } function RemoveTabFromList(tabId) { let tab = document.getElementById(tabId); if (tab != null) { tab.parentNode.removeChild(tab); } } 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"); if(Tab.nextSibling != null) { PinList.insertBefore(tabs[i], Tab.nextSibling); } else { PinList.appendChild(tabs[i]); } chrome.tabs.update(parseInt(tabs[i].id), {pinned: true}); } } } else { if (GroupList.childNodes.length > 0) { // flatten out children GroupList.insertBefore(Tab, GroupList.childNodes[0]); } else { GroupList.appendChild(Tab); } Tab.classList.remove("pin"); Tab.classList.remove("attention"); Tab.classList.add("tab"); RefreshExpandStates(); } chrome.tabs.update(parseInt(tabId), {pinned: pin}); RefreshGUI(); } } function SetActiveTab(tabId) { let Tab = document.getElementById(tabId); if (Tab != null) { document.querySelectorAll(".selected_folder").forEach(function(s){ s.classList.remove("selected_folder"); }); 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"); }); document.querySelectorAll(".highlighted_drop_target").forEach(function(s){ s.classList.remove("highlighted_drop_target"); }); Tab.classList.remove("attention"); Tab.classList.add("active_tab"); ScrollToTab(tabId); if (Tab.classList.contains("tab")) { SetActiveTabInGroup(active_group, tabId); } } } function ScrollToTab(tabId) { 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; } else { 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; } } } 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; } } } } } function Detach(tabsIds, Folders) { chrome.windows.get(CurrentWindowId, {populate : true}, function(window) { if (window.tabs.length == 1 || tabsIds.length == 0) { return; } if (tabsIds.length == window.tabs.length) { if (opt.debug) console.log("You are trying to detach all tabs! Skipping!"); return; } chrome.windows.create({tabId: tabsIds[0], state:window.state}, function(new_window) { 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" : "")) ); }); tabsIds.forEach(function(tabId) { chrome.tabs.move(tabId, {windowId: new_window.id, index:-1}, function(MovedTab) { 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 Ind++; if (Ind >= Parents.length-1) { // chrome.tabs.remove(new_window.tabs[0].id, null); let Confirmations = 0; let GiveUpLimit = 600; if (opt.debug) console.log("Detach - Remote Append and Update Loop, waiting for confirmations after attach tabs"); 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--; if (opt.debug) console.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"); 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); } } } }); }); }); }); } function CloseTabs(tabsIds) { let activeTab = document.querySelector(".pin.active_tab, #"+active_group+" .tab.active_tab"); if (activeTab != null && tabsIds.indexOf(parseInt(activeTab.id)) != -1) { SwitchActiveTabBeforeClose(active_group); } tabsIds.forEach(function(tabId) { let tab = document.getElementById(tabId); if (tab.classList.contains("pin") && opt.allow_pin_close) { tab.parentNode.removeChild(tab); chrome.tabs.update(tabId, {pinned: false}); } if (tabId == tabsIds[tabsIds.length-1]) { setTimeout(function() { chrome.tabs.remove(tabsIds, null); }, 10); } }); } function DiscardTabs(tabsIds) { var delay = 100; let tabNode = document.getElementById(tabsIds[0]); if (tabNode == null || tabNode.classList.contains("discarded") || tabNode.classList.contains("active_tab")) { delay = 5; } else { chrome.tabs.discard(tabsIds[0]); } tabsIds.splice(0, 1); if (tabsIds.length > 0) { setTimeout(function() { DiscardTabs(tabsIds); }, delay); } } function SwitchActiveTabBeforeClose(ActiveGroupId) { if (opt.debug) console.log("function: SwitchActiveTabBeforeClose"); let activeGroup = document.getElementById(ActiveGroupId); if (document.querySelectorAll("#"+ActiveGroupId+" .tab").length <= 1 && document.querySelector(".pin.active_tab") == null) { 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; } } else { SetActiveGroup("tab_list", true, true); } } else { 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; } } else { SetActiveGroup("tab_list", true, true); } } } else { if (opt.after_closing_active_tab == "above") { ActivatePrevTab(true); } if (opt.after_closing_active_tab == "below") { ActivateNextTab(true); } if (opt.after_closing_active_tab == "above_seek_in_parent") { ActivatePrevTabBeforeClose(); } if (opt.after_closing_active_tab == "below_seek_in_parent") { ActivateNextTabBeforeClose(); } } } function ActivateNextTabBeforeClose() { let activePin = document.querySelector(".pin.active_tab"); if (activePin != null) { if (activePin.nextSibling != null) { chrome.tabs.update(parseInt(activePin.nextSibling.id), { active: true }); } else { if (activePin.previousSibling != null) { chrome.tabs.update(parseInt(activePin.previousSibling.id), { active: true }); } } } let activeTab = document.querySelector("#"+active_group+" .tab.active_tab"); if (activeTab != null && document.querySelectorAll("#"+active_group+" .tab").length > 1) { if (opt.promote_children && activeTab.lastChild.firstChild != null) { chrome.tabs.update(parseInt(activeTab.lastChild.firstChild.id), { active: true }); } else { if (activeTab.nextSibling != null) { chrome.tabs.update(parseInt(activeTab.nextSibling.id), { active: true }); } else { if (activeTab.previousSibling != null) { chrome.tabs.update(parseInt(activeTab.previousSibling.id), { active: true }); } else { if (activeTab.parentNode.parentNode.classList.contains("tab")) { chrome.tabs.update(parseInt(activeTab.parentNode.parentNode.id), { active: true }); } else { ActivatePrevTab(); } } } } } } function ActivatePrevTabBeforeClose() { let activePin = document.querySelector(".pin.active_tab"); if (activePin != null) { if (activePin.previousSibling != null) { chrome.tabs.update(parseInt(activePin.previousSibling.id), { active: true }); } else { if (activePin.nextSibling != null) { chrome.tabs.update(parseInt(activePin.nextSibling.id), { active: true }); } } } let activeTab = document.querySelector("#"+active_group+" .tab.active_tab"); if (activeTab != null && document.querySelectorAll("#"+active_group+" .tab").length > 1) { if (opt.promote_children && activeTab.lastChild.firstChild != null) { chrome.tabs.update(parseInt(activeTab.lastChild.firstChild.id), { active: true }); } else { if (activeTab.previousSibling != null) { chrome.tabs.update(parseInt(activeTab.previousSibling.id), { active: true }); } else { if (activeTab.nextSibling != null) { chrome.tabs.update(parseInt(activeTab.nextSibling.id), { active: true }); } else { if (activeTab.parentNode.parentNode.classList.contains("tab")) { chrome.tabs.update(parseInt(activeTab.parentNode.parentNode.id), { active: true }); } else { ActivateNextTab(); } } } } } } 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 }); } else { if (activePin.previousSibling != null && allow_reverse) { chrome.tabs.update(parseInt(activePin.previousSibling.id), { active: true }); } } } let activeTab = document.querySelector("#"+active_group+" .tab.active_tab"); if (activeTab != null && document.querySelectorAll("#"+active_group+" .tab").length > 1) { let FirstChild = activeTab.lastChild.firstChild; if (FirstChild != null) { chrome.tabs.update(parseInt(FirstChild.id), { active: true }); } else { if (activeTab.nextSibling != null) { chrome.tabs.update(parseInt(activeTab.nextSibling.id), { active: true }); } else { 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 }); } else { if (allow_reverse) { ActivatePrevTab(); } } } } } } 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 }); } else { if (activePin.nextSibling != null && allow_reverse) { chrome.tabs.update(parseInt(activePin.nextSibling.id), { active: true }); } } } let activeTab = document.querySelector("#"+active_group+" .tab.active_tab"); 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 }); } else { if (activeTab.previousSibling != null) { chrome.tabs.update(parseInt(activeTab.previousSibling.id), { active: true }); } else { if (activeTab.parentNode.parentNode.classList.contains("tab")) { chrome.tabs.update(parseInt(activeTab.parentNode.parentNode.id), { active: true }); } else { if (allow_reverse) { ActivateNextTab(); } } } } } } function DeselectTabs() { document.querySelectorAll(".pin.selected_tab, #"+active_group+" .selected_tab").forEach(function(s){ s.classList.remove("selected_tab"); s.classList.remove("selected_last"); }); } function HighlightNode(Node) { document.querySelectorAll(".highlighted_drop_target").forEach(function(s){ s.classList.remove("highlighted_drop_target"); }); Node.classList.add("highlighted_drop_target"); } function HighlightDragEnter(Node, addDepth, Class) { // Class == "tab" or "folder" // PIN,TAB==>TAB OR PIN,TAB==>FOLDER // AND AVOID ENTERING INSIDE OWN CHILDREN if (Node.classList.contains("highlighted_drop_target") == false && Node.parentNode.classList.contains("dragged_tree") == false && Node.parentNode.classList.contains("dragged_selected") == false) { if (opt.max_tree_depth >= 0 && DragAndDrop.Depth >= 0 && DragAndDrop.DragNodeClass == Class) { let Parents = GetParentsByClass(Node, Class); if ((Parents.length + DragAndDrop.Depth <= opt.max_tree_depth + addDepth) || (Node.parentNode.parentNode.parentNode.classList.contains("group") && Node.classList.contains("drag_enter_center") == false)) { HighlightNode(Node); } } else { HighlightNode(Node); } } } 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); } } else { 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(); } } } } } 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++; } }); } 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++; } }); } } 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"); } } } } 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"); } } } 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)]); } } 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}); } }