915 lines
51 KiB
JavaScript
915 lines
51 KiB
JavaScript
class Tabs_ttTab {
|
|
constructor(p) {
|
|
this.id = p.tab.id;
|
|
this.pinned = p.tab.pinned;
|
|
if (document.getElementById(p.tab.id) != null && tt.tabs[p.tab.id]) {
|
|
tt.tabs[p.tab.id].GetFaviconAndTitle(p.addCounter);
|
|
return;
|
|
}
|
|
let ClassList = p.tab.pinned ? "pin" : "tab";
|
|
if (p.tab.discarded) ClassList += " discarded";
|
|
if (p.tab.attention) ClassList += " attention";
|
|
if (p.AdditionalClass) ClassList += " " + p.AdditionalClass;
|
|
if (p.ExpandState) ClassList += " " + p.ExpandState;
|
|
let DIV_Tab = DOM_New("div", undefined, {id: p.tab.id, className: ClassList});
|
|
let DIV_header = DOM_New("div", DIV_Tab, {id: ("tab_header_" + p.tab.id), className: (opt.always_show_close && !opt.never_show_close) ? "tab_header close_show" : "tab_header", draggable: (!p.SkipSetEvents ? true : false)});
|
|
let DIV_expand = DOM_New("div", DIV_header, {id: ("exp_" + p.tab.id), className: "expand"});
|
|
let DIV_counter = DOM_New("div", DIV_header, {id: ("tab_counter_" + p.tab.id), className: "tab_counter"});
|
|
DOM_New("div", DIV_counter, {id: ("counter_number_" + p.tab.id), className: "counter_number"});
|
|
let DIV_title = DOM_New("div", DIV_header, {id: ("tab_title_" + p.tab.id), className: "tab_title"});
|
|
let DIV_close_button = DOM_New("div", DIV_header, {id: ("close_" + p.tab.id), className: (opt.never_show_close ? "close hidden" : "close")});
|
|
DOM_New("div", DIV_close_button, {id: ("close_img_" + p.tab.id), className: (opt.never_show_close ? "close_img hidden" : "close_img")});
|
|
let DIV_audio_indicator = DOM_New("div", DIV_header, {id: ("tab_mediaicon_" + p.tab.id), className: "tab_mediaicon"});
|
|
let DIV_children = DOM_New("div", DIV_Tab, {id: ("°" + p.tab.id), className: "children"});
|
|
DOM_New("div", DIV_Tab, {id: ("drag_indicator_" + p.tab.id), className: "drag_indicator"});
|
|
if (!p.SkipSetEvents) {
|
|
DIV_children.onclick = function(event) {
|
|
if (event.target == this && event.which == 1) DOM_Deselect();
|
|
}
|
|
DIV_children.onmousedown = function(event) {
|
|
if (event.target == this) {
|
|
if (event.which == 2 && event.target == this && opt.midclick_tab !== "close_tab") {
|
|
event.stopImmediatePropagation();
|
|
Tabs_ActionClickTab(this.parentNode, opt.midclick_tab);
|
|
}
|
|
if (event.which == 3) Menu_ShowFGlobalMenu(event);
|
|
}
|
|
}
|
|
DIV_children.ondblclick = function(event) {
|
|
if (event.target == this) Tabs_ActionClickTab(this.parentNode, opt.dbclick_tab);
|
|
}
|
|
DIV_expand.onmousedown = function(event) {
|
|
if (tt.DOMmenu.style.top != "-1000px") Menu_HideMenus();
|
|
if (event.which == 1 && !event.shiftKey && !event.ctrlKey) DOM_EventExpandBox(this.parentNode.parentNode);
|
|
}
|
|
DIV_expand.onmouseenter = function(event) {
|
|
this.classList.add("hover");
|
|
}
|
|
DIV_expand.onmouseleave = function(event) {
|
|
this.classList.remove("hover");
|
|
}
|
|
if (!opt.never_show_close) {
|
|
DIV_close_button.onmousedown = function(event) {
|
|
event.stopImmediatePropagation();
|
|
if (event.which != 3) Tabs_CloseTabs([parseInt(this.parentNode.parentNode.id)]);
|
|
}
|
|
DIV_close_button.onmouseenter = function(event) {
|
|
this.classList.add("close_hover");
|
|
}
|
|
DIV_close_button.onmouseleave = function(event) {
|
|
this.classList.remove("close_hover");
|
|
}
|
|
}
|
|
DIV_header.ondblclick = function(event) {
|
|
if (event.target.classList && event.target.classList.contains("tab_header")) Tabs_ActionClickTab(this.parentNode, opt.dbclick_tab);
|
|
}
|
|
DIV_header.onmousedown = function(event) {
|
|
if (browserId == "V") {
|
|
chrome.windows.getCurrent({populate: false}, function(window) {
|
|
if (tt.CurrentWindowId != window.id && window.focused) location.reload();
|
|
});
|
|
}
|
|
event.stopImmediatePropagation();
|
|
if (event.which == 1) {
|
|
if (tt.DOMmenu.style.top != "-1000px") {
|
|
Menu_HideMenus();
|
|
} else {
|
|
if (event.shiftKey || event.ctrlKey) {
|
|
DOM_Select(event, this.parentNode);
|
|
}
|
|
}
|
|
}
|
|
if (event.which == 2) {
|
|
event.preventDefault();
|
|
Tabs_ActionClickTab(this.parentNode, opt.midclick_tab);
|
|
}
|
|
if (event.which == 3) Menu_ShowTabMenu(this.parentNode, event);
|
|
}
|
|
DIV_header.onclick = function(event) {
|
|
if (!event.shiftKey && !event.ctrlKey) {
|
|
DOM_Deselect();
|
|
if (event.target.classList.contains("tab_header")) {
|
|
chrome.tabs.update(parseInt(this.parentNode.id), {active: true});
|
|
}
|
|
}
|
|
}
|
|
DIV_header.onmouseover = function(event) {
|
|
this.classList.add("tab_header_hover");
|
|
if (opt.never_show_close == false && opt.always_show_close == false) this.classList.add("close_show");
|
|
}
|
|
DIV_header.onmouseleave = function(event) {
|
|
this.classList.remove("tab_header_hover");
|
|
if (opt.never_show_close == false && opt.always_show_close == false) this.classList.remove("close_show");
|
|
}
|
|
DIV_header.ondragstart = function(event) { // DRAG START
|
|
tt.Dragging = true;
|
|
tt.DraggingGroup = false;
|
|
event.stopPropagation();
|
|
event.dataTransfer.setDragImage(document.getElementById("DragImage"), 0, 0);
|
|
event.dataTransfer.setData("text", "");
|
|
event.dataTransfer.setData("SourceWindowId", tt.CurrentWindowId);
|
|
DOM_CleanUpDragAndDrop();
|
|
let Nodes = [];
|
|
if (this.parentNode.classList.contains("selected")) {
|
|
DOM_FreezeSelection(false);
|
|
} else {
|
|
DOM_FreezeSelection(true);
|
|
DOM_SetClasses(this.parentNode, ["selected_temporarly", "selected"], [], []);
|
|
}
|
|
DOM_RemoveHeadersHoverClass();
|
|
let selected = document.querySelectorAll(".selected, .selected .tab, .selected .folder");
|
|
for (let s of selected) {
|
|
s.classList.add("dragged_tree");
|
|
if (s.classList.contains("pin")) {
|
|
tt.DraggingPin = true;
|
|
Nodes.push({id: s.id, parent: s.parentNode.id, selected: s.classList.contains("selected"), temporary: s.classList.contains("selected_temporarly"), NodeClass: "pin"});
|
|
}
|
|
if (s.classList.contains("tab")) {
|
|
tt.DraggingTab = true;
|
|
Nodes.push({id: s.id, parent: s.parentNode.id, selected: s.classList.contains("selected"), temporary: s.classList.contains("selected_temporarly"), NodeClass: "tab"});
|
|
}
|
|
if (s.classList.contains("folder")) {
|
|
tt.DraggingFolder = true;
|
|
Nodes.push({id: s.id, parent: s.parentNode.id, selected: s.classList.contains("selected"), temporary: s.classList.contains("selected_temporarly"), NodeClass: "folder", index: (tt.folders[s.id] ? tt.folders[s.id].index : 0), name: (tt.folders[s.id] ? tt.folders[s.id].name : labels.noname_group), expand: (tt.folders[s.id] ? tt.folders[s.id].expand : "")});
|
|
}
|
|
}
|
|
if (opt.max_tree_drag_drop && opt.max_tree_depth >= 0) {
|
|
let dragged_tree = document.querySelectorAll(".dragged_tree .tab, .dragged_tree .folder");
|
|
for (let s of dragged_tree) {
|
|
let parents = DOM_GetParentsByClass(s.parentNode, "dragged_tree");
|
|
if (parents.length > tt.DragTreeDepth) tt.DragTreeDepth = parents.length;
|
|
}
|
|
} else {
|
|
tt.DragTreeDepth = -1;
|
|
}
|
|
let Parents = DOM_GetAllParents(this.parentNode);
|
|
for (let s of Parents) {
|
|
if (s.classList && (s.classList.contains("tab") || s.classList.contains("folder"))) s.classList.add("dragged_parents");
|
|
}
|
|
event.dataTransfer.setData("Nodes", JSON.stringify(Nodes));
|
|
event.dataTransfer.setData("NodesTypes", JSON.stringify({DraggingGroup: tt.DraggingGroup, DraggingPin: tt.DraggingPin, DraggingTab: tt.DraggingTab, DraggingFolder: tt.DraggingFolder}));
|
|
chrome.runtime.sendMessage({command: "drag_start", DragTreeDepth: tt.DragTreeDepth, DraggingGroup: tt.DraggingGroup, DraggingPin: tt.DraggingPin, DraggingTab: tt.DraggingTab, DraggingFolder: tt.DraggingFolder});
|
|
}
|
|
DIV_header.ondragenter = function(event) {
|
|
this.classList.remove("tab_header_hover");
|
|
}
|
|
DIV_header.ondragleave = function(event) {
|
|
DOM_RemoveHighlight();
|
|
}
|
|
DIV_header.ondragover = function(event) {
|
|
if (tt.DraggingGroup == false && (tt.DraggingPin || tt.DraggingTab || tt.DraggingFolder) && this.parentNode.classList.contains("dragged_tree") == false) {
|
|
if (this.parentNode.classList.contains("pin")) {
|
|
if (this.parentNode.classList.contains("before") == false && event.layerX < this.clientWidth / 2) {
|
|
DOM_RemoveHighlight();
|
|
DOM_SetClasses(this.parentNode, ["before", "highlighted_drop_target"], ["after"], []);
|
|
}
|
|
if (this.parentNode.classList.contains("after") == false && event.layerX >= this.clientWidth / 2) {
|
|
DOM_RemoveHighlight();
|
|
DOM_SetClasses(this.parentNode, ["after", "highlighted_drop_target"], ["before"], []);
|
|
}
|
|
}
|
|
if (this.parentNode.classList.contains("tab")) {
|
|
let TabDepth = Tabs_GetTabDepthInTree(this);
|
|
let PDepth = TabDepth + tt.DragTreeDepth;
|
|
let PIsGroup = this.parentNode.parentNode.parentNode.classList.contains("group");
|
|
// let PIsTab = this.parentNode.parentNode.parentNode.classList.contains("tab");
|
|
let PIsFolder = this.parentNode.parentNode.parentNode.classList.contains("folder");
|
|
let PIsDraggedParents = this.parentNode.classList.contains("dragged_parents");
|
|
if ((PIsFolder == tt.DraggingFolder || tt.DraggingFolder == false || PIsGroup == true) && this.parentNode.classList.contains("before") == false && event.layerY < this.clientHeight / 3 && (PDepth <= opt.max_tree_depth + 1 || opt.max_tree_depth < 0 || opt.max_tree_drag_drop == false || PIsDraggedParents == true)) {
|
|
DOM_RemoveHighlight();
|
|
DOM_SetClasses(this.parentNode, ["before", "highlighted_drop_target"], ["inside", "after"], []);
|
|
}
|
|
if (tt.DraggingFolder == false && this.parentNode.classList.contains("inside") == false && event.layerY > this.clientHeight / 3 && event.layerY <= 2 * (this.clientHeight / 3) && (PDepth <= opt.max_tree_depth || opt.max_tree_depth < 0 || opt.max_tree_drag_drop == false || PIsDraggedParents == true)) {
|
|
DOM_RemoveHighlight();
|
|
DOM_SetClasses(this.parentNode, ["inside", "highlighted_drop_target"], ["before", "after"], []);
|
|
}
|
|
if ((PIsFolder == tt.DraggingFolder || tt.DraggingFolder == false || PIsGroup == true) && this.parentNode.classList.contains("after") == false && this.parentNode.classList.contains("o") == false && event.layerY > 2 * (this.clientHeight / 3) && (PDepth <= opt.max_tree_depth + 1 || opt.max_tree_depth < 0 || opt.max_tree_drag_drop == false || PIsDraggedParents == true)) {
|
|
DOM_RemoveHighlight();
|
|
DOM_SetClasses(this.parentNode, ["after", "highlighted_drop_target"], ["before", "inside"], []);
|
|
}
|
|
}
|
|
}
|
|
if (opt.open_tree_on_hover && tt.DragOverId != this.id) {
|
|
if (this.parentNode.classList.contains("c") && this.parentNode.classList.contains("dragged_tree") == false) {
|
|
clearTimeout(tt.DragOverTimer);
|
|
tt.DragOverId = this.id;
|
|
let This = this;
|
|
tt.DragOverTimer = setTimeout(function() {
|
|
if (tt.DragOverId == This.id) DOM_SetClasses(This.parentNode, ["o"], ["c"], []);
|
|
}, 1500);
|
|
}
|
|
}
|
|
}
|
|
DIV_header.ondragend = function(event) {
|
|
if (opt.open_tree_on_hover) {
|
|
clearTimeout(tt.DragOverTimer);
|
|
tt.DragOverId = "";
|
|
}
|
|
setTimeout(function() {DOM_CleanUpDragAndDrop();}, 300);
|
|
setTimeout(function() {chrome.runtime.sendMessage({command: "drag_end"});}, 500);
|
|
}
|
|
DIV_audio_indicator.onmousedown = function(event) {
|
|
event.stopImmediatePropagation();
|
|
if (event.which == 1 && (this.parentNode.parentNode.classList.contains("audible") || this.parentNode.parentNode.classList.contains("muted"))) {
|
|
chrome.tabs.get(parseInt(this.parentNode.parentNode.id), function(tab) {
|
|
if (tab) chrome.tabs.update(tab.id, {muted: !tab.mutedInfo.muted});
|
|
});
|
|
}
|
|
}
|
|
}
|
|
let parent;
|
|
if (p.tab.pinned == true) {
|
|
parent = document.getElementById("pin_list");
|
|
} else {
|
|
if (p.ParentId == false || p.ParentId == undefined || p.ParentId == "pin_list") {
|
|
parent = document.getElementById("°" + tt.active_group);
|
|
} else {
|
|
parent = document.getElementById(p.ParentId);
|
|
if (parent == null || parent.classList.contains("pin") || parent.parentNode.classList.contains("pin")) {
|
|
parent = document.getElementById("°" + tt.active_group);
|
|
} else {
|
|
parent = document.getElementById("°" + p.ParentId);
|
|
if (parent.children.length == 0) DOM_SetClasses(parent.parentNode, ["o"], ["c"], []);
|
|
}
|
|
}
|
|
}
|
|
if (p.Append == true && parent) parent.appendChild(DIV_Tab);
|
|
if ((p.Append == false || p.Append == undefined) && parent) parent.prepend(DIV_Tab);
|
|
if (p.InsertAfterId) {
|
|
let After = document.getElementById(p.InsertAfterId);
|
|
if (After != null) {
|
|
if ((p.tab.pinned && After.classList.contains("pin")) || (p.tab.pinned == false && (After.classList.contains("tab") || After.classList.contains("folder")))) {
|
|
DOM_InsterAfterNode(DIV_Tab, After);
|
|
} else {
|
|
parent.appendChild(DIV_Tab);
|
|
}
|
|
} else {
|
|
parent.appendChild(DIV_Tab);
|
|
}
|
|
}
|
|
this.Node = DIV_Tab;
|
|
this.title = DIV_title;
|
|
if (!p.SkipFavicon) this.GetFaviconAndTitle(p.addCounter);
|
|
if (!p.SkipMediaIcon) this.RefreshMediaIcon(p.tab.id);
|
|
if (p.RefreshDiscarded) this.RefreshDiscarded();
|
|
if (p.tab.active && !p.SkipSetActive) Tabs_SetActiveTab(p.tab.id);
|
|
if (p.Scroll) this.ScrollToTab();
|
|
}
|
|
RemoveTab() {
|
|
if (opt.debug) Utils_log("f: RemoveTab, tabId: " + this.id);
|
|
if (this.Node != null) {
|
|
this.Node.parentNode.removeChild(this.Node);
|
|
if (tt.tabs[this.id]) delete tt.tabs[this.id];
|
|
}
|
|
}
|
|
ScrollToTab() {
|
|
let Tab = this.Node;
|
|
let P = document.getElementById("pin_list");
|
|
let G = document.getElementById(tt.active_group);
|
|
if (Tab != null) {
|
|
if (Tab.classList.contains("pin")) {
|
|
if (Tab.getBoundingClientRect().left - P.getBoundingClientRect().left < 0) {
|
|
P.scrollLeft = P.scrollLeft + Tab.getBoundingClientRect().left - P.getBoundingClientRect().left - 2;
|
|
} else {
|
|
if (Tab.getBoundingClientRect().left - P.getBoundingClientRect().left > G.getBoundingClientRect().width - document.querySelector(".tab_header").getBoundingClientRect().width) {
|
|
P.scrollLeft = P.scrollLeft + Tab.getBoundingClientRect().left - P.getBoundingClientRect().left - P.getBoundingClientRect().width + document.querySelector(".tab_header").getBoundingClientRect().width + 2;
|
|
}
|
|
}
|
|
} else if (Tab.classList.contains("tab") && document.querySelector("#" + tt.active_group + " [id='" + this.id + "']") != null) {
|
|
let Parents = DOM_GetParentsByClass(Tab, "c");
|
|
if (Parents.length > 0) {
|
|
for (let s of Parents) {
|
|
DOM_SetClasses(s, ["o"], ["c"], []);
|
|
}
|
|
}
|
|
if (Tab.getBoundingClientRect().top - G.getBoundingClientRect().top < 0) {
|
|
G.scrollTop = G.scrollTop + Tab.getBoundingClientRect().top - G.getBoundingClientRect().top - 2;
|
|
} else {
|
|
if (Tab.getBoundingClientRect().top - G.getBoundingClientRect().top > G.getBoundingClientRect().height - document.querySelector(".tab_header").getBoundingClientRect().height) {
|
|
G.scrollTop = G.scrollTop + Tab.getBoundingClientRect().top - G.getBoundingClientRect().top - G.getBoundingClientRect().height + document.querySelector(".tab_header").getBoundingClientRect().height + 10;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SetTabClass(pin) {
|
|
let GroupList = document.getElementById("°" + tt.active_group);
|
|
let Tab = this.Node;
|
|
if (Tab != null) {
|
|
if (pin) {
|
|
if (Tab.parentNode.id != "pin_list") document.getElementById("pin_list").appendChild(Tab);
|
|
DOM_SetClasses(Tab, ["pin"], ["tab", "o", "c"], []);
|
|
if (Tab.childNodes[1].childNodes.length > 0) { // flatten out children
|
|
let tabs = document.querySelectorAll("#°" + Tab.id + " .pin, #°" + Tab.id + " .tab");
|
|
for (let tab of tabs) {
|
|
DOM_SetClasses(tab, ["pin"], ["tab", "o", "c"], []);
|
|
DOM_InsterAfterNode(tab, Tab);
|
|
chrome.tabs.update(parseInt(tab.id), {pinned: true});
|
|
}
|
|
let folders = document.querySelectorAll("#°" + Tab.id + " .folder");
|
|
for (let i = folders.length - 1; i >= 0; i--) {
|
|
GroupList.prepend(folders[i]);
|
|
}
|
|
}
|
|
chrome.tabs.update(parseInt(Tab.id), {pinned: true});
|
|
} else {
|
|
if (Tab.parentNode.id == "pin_list") { // if coming from pin_list
|
|
if (GroupList.childNodes.length > 0) {
|
|
GroupList.insertBefore(Tab, GroupList.childNodes[0]);
|
|
} else {
|
|
GroupList.appendChild(Tab);
|
|
}
|
|
}
|
|
DOM_SetClasses(Tab, ["tab"], ["pin", "attention"], []);
|
|
DOM_RefreshExpandStates();
|
|
chrome.tabs.update(parseInt(Tab.id), {pinned: false});
|
|
}
|
|
DOM_RefreshGUI();
|
|
}
|
|
}
|
|
DuplicateTab() {
|
|
let OriginalTabNode = this.Node;
|
|
chrome.tabs.duplicate(parseInt(this.id), function(tab) {
|
|
let DupRetry = setInterval(function() {
|
|
let DupTab = document.getElementById(tab.id);
|
|
if (DupTab != null && OriginalTabNode != null) {
|
|
if (browserId == "F" && tab.pinned) DOM_SetClasses(DupTab, ["pin"], ["tab"], []);
|
|
DOM_InsterAfterNode(DupTab, OriginalTabNode);
|
|
DOM_RefreshExpandStates();
|
|
tt.schedule_update_data++;
|
|
DOM_RefreshCounters();
|
|
clearInterval(DupRetry);
|
|
}
|
|
}, 10);
|
|
setTimeout(function() {
|
|
if (DupRetry) clearInterval(DupRetry);
|
|
}, 500);
|
|
});
|
|
}
|
|
GetFaviconAndTitle(addCounter) {
|
|
let t = document.getElementById(this.id);
|
|
let tTitle = this.title;
|
|
if (t != null) {
|
|
chrome.tabs.get(parseInt(t.id), async function(tab) {
|
|
if (tab) {
|
|
let title = tab.title ? tab.title : tab.url;
|
|
let tHeader = t.childNodes[0];
|
|
if (tab.status == "complete" || tab.discarded) {
|
|
t.classList.remove("loading");
|
|
tTitle.textContent = title;
|
|
tHeader.title = title;
|
|
if (opt.show_counter_tabs_hints) tHeader.setAttribute("tabTitle", title);
|
|
let Img = new Image();
|
|
let CachedFavicon = browserId == "F" ? await browser.sessions.getTabValue(tab.id, "CachedFaviconUrl") : "chrome://favicon/" + tab.url;
|
|
let TryCases = [tab.favIconUrl, CachedFavicon, "./theme/icon_empty.svg"];
|
|
Tabs_LoadFavicon(tab.id, Img, TryCases, tHeader, 0);
|
|
}
|
|
if (tab.status == "loading" && tab.discarded == false) {
|
|
title = tab.title ? tab.title : labels.loading;
|
|
t.classList.add("loading");
|
|
tHeader.style.backgroundImage = "";
|
|
tHeader.title = labels.loading;
|
|
if (opt.show_counter_tabs_hints) tHeader.setAttribute("tabTitle", labels.loading);
|
|
tTitle.textContent = labels.loading;
|
|
setTimeout(function() {
|
|
if (document.getElementById(tab.id) != null && tt.tabs[tab.id]) tt.tabs[tab.id].GetFaviconAndTitle(addCounter);
|
|
}, 1000);
|
|
}
|
|
if (addCounter && (opt.show_counter_tabs || opt.show_counter_tabs_hints)) tt.tabs[t.id].RefreshTabCounter();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
RefreshDiscarded() { // set discarded class
|
|
let t = document.getElementById(this.id);
|
|
if (t != null) {
|
|
chrome.tabs.get(parseInt(t.id), function(tab) {
|
|
if (tab) {
|
|
if (tab.discarded) {
|
|
DOM_SetClasses(t, ["discarded"], ["audible", "muted"], []);
|
|
} else {
|
|
t.classList.remove("discarded");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
SetAttentionIcon() { // set attention class
|
|
let t = document.getElementById(this.id);
|
|
if (t != null) t.classList.add("attention");
|
|
}
|
|
RefreshMediaIcon() { // change media icon
|
|
let t = document.getElementById(this.id);
|
|
if (t != null) {
|
|
chrome.tabs.get(parseInt(t.id), function(tab) {
|
|
if (tab) {
|
|
if (tab.mutedInfo.muted && !tab.discarded) DOM_SetClasses(t, ["muted"], ["audible"], []);
|
|
if (!tab.mutedInfo.muted && tab.audible && !tab.discarded) DOM_SetClasses(t, ["audible"], ["muted"], []);
|
|
if ((!tab.mutedInfo.muted && !tab.audible) || tab.discarded) DOM_SetClasses(t, [], ["audible", "muted"], []);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
RefreshTabCounter() {
|
|
let t = document.getElementById(this.id);
|
|
if (t != null && t.childNodes[0]) {
|
|
let title = t.childNodes[0].getAttribute("tabTitle");
|
|
if (t != null && title != null) {
|
|
if (t.classList.contains("o") || t.classList.contains("c")) {
|
|
if (opt.show_counter_tabs) t.childNodes[0].childNodes[1].childNodes[0].textContent = document.querySelectorAll("[id='" + t.id + "'] .tab").length;
|
|
if (opt.show_counter_tabs_hints) t.childNodes[0].title = (document.querySelectorAll("[id='" + t.id + "'] .tab").length + " • ") + title;
|
|
} else {
|
|
t.childNodes[0].title = title;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async function Tabs_LoadFavicon(tabId, Img, TryUrls, TabHeaderNode, i) {
|
|
if (TabHeaderNode) {
|
|
Img.src = TryUrls[i];
|
|
Img.onload = function() {
|
|
TabHeaderNode.style.backgroundImage = "url(" + TryUrls[i] + ")";
|
|
if (browserId == "F") browser.sessions.setTabValue(tabId, "CachedFaviconUrl", TryUrls[i]); // cache Firefox favicon - solution for bug with empty favicons in unloaded tabs
|
|
};
|
|
Img.onerror = function() {
|
|
if (i < TryUrls.length) Tabs_LoadFavicon(tabId, Img, TryUrls, TabHeaderNode, (i + 1));
|
|
}
|
|
}
|
|
}
|
|
|
|
async function Tabs_SaveTabs() {
|
|
setInterval(function() {
|
|
if (tt.schedule_update_data > 1) tt.schedule_update_data = 1;
|
|
if (tt.schedule_update_data > 0) {
|
|
if (opt.debug) Utils_log("f: Tabs_SaveTabs");
|
|
let pins_data = [];
|
|
let tabs_data = [];
|
|
for (let tabId in tt.tabs) {
|
|
if (tt.tabs[tabId].Node != null && tt.tabs[tabId].Node.parentNode != null) {
|
|
if (tt.tabs[tabId].pinned) {
|
|
pins_data.push({id: tabId, parent: "pin_list", index: Array.from(tt.tabs[tabId].Node.parentNode.children).indexOf(tt.tabs[tabId].Node), expand: ""});
|
|
} else {
|
|
tabs_data.push({id: tabId, parent: tt.tabs[tabId].Node.parentNode.parentNode.id, index: Array.from(tt.tabs[tabId].Node.parentNode.children).indexOf(tt.tabs[tabId].Node), expand: (tt.tabs[tabId].Node.classList.contains("c") ? "c" : (tt.tabs[tabId].Node.classList.contains("o") ? "o" : ""))});
|
|
}
|
|
}
|
|
}
|
|
chrome.runtime.sendMessage({command: "update_all_tabs", pins: pins_data, tabs: tabs_data});
|
|
tt.schedule_update_data--;
|
|
}
|
|
}, 1000);
|
|
}
|
|
|
|
async function Tabs_RearrangeBrowserTabs() {
|
|
if (opt.debug) Utils_log("f: Tabs_RearrangeBrowserTabs");
|
|
setInterval(function() {
|
|
if (tt.schedule_rearrange_tabs > 0) {
|
|
tt.schedule_rearrange_tabs--;
|
|
if (opt.debug) Utils_log("f: RearrangeBrowserTabs");
|
|
chrome.tabs.query({currentWindow: true}, function(tabs) {
|
|
let ttTabIds = Array.prototype.map.call(document.querySelectorAll(".pin, .tab"), function(s) {return parseInt(s.id);});
|
|
let tabIds = Array.prototype.map.call(tabs, function(t) {return t.id;});
|
|
Tabs_RearrangeBrowserTabsLoop(ttTabIds, tabIds, ttTabIds.length - 1);
|
|
});
|
|
}
|
|
}, 1000);
|
|
}
|
|
|
|
async function Tabs_RearrangeBrowserTabsLoop(ttTabIds, tabIds, tabIndex) {
|
|
if (opt.debug) Utils_log("f: RearrangeBrowserTabsLoop");
|
|
if (tabIndex >= 0 && tt.schedule_rearrange_tabs == 0) {
|
|
if (ttTabIds[tabIndex] != tabIds[tabIndex]) chrome.tabs.move(ttTabIds[tabIndex], {index: tabIndex});
|
|
setTimeout(function() {
|
|
Tabs_RearrangeBrowserTabsLoop(ttTabIds, tabIds, (tabIndex - 1));
|
|
}, 0);
|
|
}
|
|
}
|
|
|
|
function Tabs_RearrangeTree(TTtabs, TTfolders, show_finish_in_status) {
|
|
if (opt.debug) Utils_log("f: Tabs_RearrangeTree");
|
|
Manager_ShowStatusBar({show: true, spinner: true, message: chrome.i18n.getMessage("status_bar_rearranging_tabs")});
|
|
let Nodes = document.querySelectorAll(".pin, .tab, .folder");
|
|
for (let Node of Nodes) {
|
|
let Sibling = Node.nextElementSibling;
|
|
if (Sibling) {
|
|
let NodeIndex = TTtabs[Node.id] ? TTtabs[Node.id].index : (TTfolders[Node.id] ? TTfolders[Node.id].index : undefined);
|
|
while (Sibling && NodeIndex) {
|
|
let SiblingIndex = TTtabs[Sibling.id] ? TTtabs[Sibling.id].index : (TTfolders[Sibling.id] ? TTfolders[Sibling.id].index : 0);
|
|
if (NodeIndex > SiblingIndex) DOM_InsterAfterNode(Node, Sibling);
|
|
Sibling = Sibling.nextElementSibling ? Sibling.nextElementSibling : false;
|
|
}
|
|
}
|
|
if (show_finish_in_status) Manager_ShowStatusBar({show: true, spinner: false, message: chrome.i18n.getMessage("status_bar_rearranging_finished"), hideTimeout: 1000});
|
|
}
|
|
}
|
|
|
|
function Tabs_Detach(Nodes, NodesTypes, Group) {
|
|
if (opt.debug) Utils_log("f: Detach");
|
|
let folderNodes = {};
|
|
let TabsIds = [];
|
|
for (let Node of Nodes) {
|
|
if (Node.NodeClass == "folder") folderNodes[Node.id] = {id: Node.id, parent: (Node.parent).substr(1), name: Node.name, index: Node.index, expand: Node.expand};
|
|
if (Node.NodeClass == "pin") TabsIds.push(parseInt(Node.id));
|
|
if (Node.NodeClass == "tab") TabsIds.push(parseInt(Node.id));
|
|
}
|
|
chrome.windows.get(tt.CurrentWindowId, {populate : true}, function(window) {
|
|
if (window.tabs.length == 1) return;
|
|
if (TabsIds.length == window.tabs.length) {
|
|
if (opt.debug) Utils_log("You are trying to detach all tabs! Skipping!");
|
|
return;
|
|
}
|
|
let params = TabsIds.length > 0 ? {tabId: TabsIds[0], state: window.state} : {state: window.state};
|
|
chrome.windows.create(params, function(new_window) {
|
|
chrome.tabs.update(new_window.tabs[0].id, {active: true});
|
|
chrome.runtime.sendMessage({command: "get_groups", windowId: new_window.id}, function(g) {
|
|
if (NodesTypes.DraggingGroup) {
|
|
let GroupsToDetach = Object.assign({}, g); // if there will be a multi groups selection, below I will need for each group loop
|
|
GroupsToDetach[Group.id] = Group;
|
|
chrome.runtime.sendMessage({command: "save_groups", groups: GroupsToDetach, windowId: new_window.id});
|
|
setTimeout(function() {Groups_GroupRemove(Group.id, false);}, 2000);
|
|
}
|
|
chrome.runtime.sendMessage({command: "save_folders", folders: folderNodes, windowId: new_window.id});
|
|
for (let Node of Nodes) {
|
|
if (Node.NodeClass == "pin") {
|
|
chrome.tabs.update(parseInt(Node.id), {pinned: true});
|
|
chrome.runtime.sendMessage({command: "update_tab", tabId: Node.id, tab: {parent: "pin_list"}});
|
|
}
|
|
if (Node.NodeClass == "tab") chrome.runtime.sendMessage({command: "update_tab", tabId: Node.id, tab: {parent: (Node.parent).substr(1)}});
|
|
if (Node.NodeClass == "folder") Folders_RemoveFolder(Node.id);
|
|
}
|
|
if (TabsIds.length > 1) {
|
|
TabsIds.splice(0, 1);
|
|
chrome.tabs.move(TabsIds, {windowId: new_window.id, index:-1}, function(MovedTabs) {
|
|
for (let Node of Nodes) {
|
|
if (Node.NodeClass == "pin") {chrome.tabs.update(parseInt(Node.id), {pinned: true});}
|
|
if (Node.NodeClass == "folder") {Folders_RemoveFolder(Node.id);}
|
|
}
|
|
let Stop = 500;
|
|
let DetachNodes = setInterval(function() {
|
|
Stop--;
|
|
let all_moved = true;
|
|
for (let Node of Nodes) {
|
|
if (document.getElementById(Node.id) != null) all_moved = false;
|
|
if (Node.NodeClass == "pin") chrome.runtime.sendMessage({command: "update_tab", tabId: Node.id, tab: {parent: "pin_list"}});
|
|
if (Node.NodeClass == "tab") chrome.runtime.sendMessage({command: "update_tab", tabId: Node.id, tab: {parent: (Node.parent).substr(1)}});
|
|
}
|
|
if (all_moved || Stop < 0) {
|
|
setTimeout(function() {
|
|
clearInterval(DetachNodes);
|
|
}, 300);
|
|
}
|
|
}, 100);
|
|
});
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
function Tabs_DiscardTabs(tabsIds) {
|
|
let delay = 100;
|
|
let tabNode = document.getElementById(tabsIds[0]);
|
|
if (tabNode == null || tabNode.classList.contains("discarded") || tabNode.classList.contains("active_tab")) {
|
|
delay = 5;
|
|
} else {
|
|
chrome.tabs.discard(tabsIds[0]);
|
|
}
|
|
tabsIds.splice(0, 1);
|
|
if (tabsIds.length > 0) {
|
|
setTimeout(function() {
|
|
Tabs_DiscardTabs(tabsIds);
|
|
}, delay);
|
|
}
|
|
}
|
|
|
|
function Tabs_FindTab(input) { // find and select tabs
|
|
let ButtonFilterClear = document.getElementById("button_filter_clear");
|
|
let Nodes = document.querySelectorAll(".filtered, .highlighted_search");
|
|
for (let s of Nodes) {
|
|
DOM_SetClasses(s, [], ["selected", "selected_last", "filtered", "highlighted_search"], []);
|
|
}
|
|
if (input.length == 0) {
|
|
document.getElementById("filter_box").value = "";
|
|
ButtonFilterClear.style.opacity = "0"; ButtonFilterClear.title = "";
|
|
return;
|
|
} else {
|
|
ButtonFilterClear.style.opacity = "1"; ButtonFilterClear.title = labels.clear_filter;
|
|
}
|
|
tt.SearchIndex = 0;
|
|
let FilterType = document.getElementById("button_filter_type");
|
|
let searchUrl = FilterType.classList.contains("url");
|
|
let searchTitle = FilterType.classList.contains("title");
|
|
let query = {windowId: tt.CurrentWindowId, pinned: false};
|
|
if (input == "*audible") query = {windowId: tt.CurrentWindowId, discarded: false, audible: true, muted: false, pinned: false};
|
|
if (input == "*muted") query = {windowId: tt.CurrentWindowId, discarded: false, muted: true, pinned: false};
|
|
if (input == "*unloaded") query = {windowId: tt.CurrentWindowId, discarded: true, pinned: false};
|
|
if (input == "*loaded") query = {windowId: tt.CurrentWindowId, discarded: false, pinned: false};
|
|
chrome.tabs.query(query, function(tabs) {
|
|
for (let Tab of tabs) {
|
|
let t = document.getElementById(Tab.id);
|
|
if (input == "*audible" || input == "*muted" || input == "*unloaded" || input == "*loaded") {
|
|
DOM_SetClasses(t, ["filtered", "selected"], [], []);
|
|
} else {
|
|
if (searchUrl) {
|
|
if (Tab.url.toLowerCase().match(input.toLowerCase())) DOM_SetClasses(t, ["filtered", "selected"], [], []);
|
|
}
|
|
if (searchTitle) {
|
|
if (Tab.title.toLowerCase().match(input.toLowerCase())) DOM_SetClasses(t, ["filtered", "selected"], [], []);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function Tabs_CloseTabs(tabsIds) {
|
|
if (opt.debug) Utils_log("f: Tabs_CloseTabs, tabsIds are: " + JSON.stringify(tabsIds));
|
|
for (let tabId of tabsIds) {
|
|
let t = document.getElementById(tabId);
|
|
if (t != null) t.classList.add("will_be_closed");
|
|
}
|
|
let activeTab = document.querySelector(".pin.active_tab, #" + tt.active_group + " .tab.active_tab");
|
|
if (activeTab != null && tabsIds.indexOf(parseInt(activeTab.id)) != -1) Tabs_SwitchActiveTabBeforeClose(tt.active_group);
|
|
setTimeout(function() {
|
|
for (let tabId of tabsIds) {
|
|
let t = document.getElementById(tabId);
|
|
if (t != null && t.classList.contains("pin") && opt.allow_pin_close) {
|
|
t.parentNode.removeChild(t);
|
|
chrome.tabs.update(tabId, {pinned: false});
|
|
chrome.runtime.sendMessage({command: "update_tab", tabId: tabId, tab: {parent: "pin_list"}});
|
|
}
|
|
if (tabId == tabsIds[tabsIds.length - 1]) {
|
|
setTimeout(function() {chrome.tabs.remove(tabsIds, null);}, 10);
|
|
DOM_RefreshGUI();
|
|
}
|
|
}
|
|
}, 200);
|
|
}
|
|
|
|
function Tabs_OpenNewTab(pin, InsertAfterTabId, ParentId, Append) {
|
|
chrome.tabs.create({pinned: pin}, function(tab) {
|
|
tt.tabs[tab.id] = new Tabs_ttTab({tab: tab, ParentId: ParentId, InsertAfterId: InsertAfterTabId, Append: Append, Scroll: true});
|
|
if (!pin && opt.move_tabs_on_url_change == "from_empty") chrome.runtime.sendMessage({command: "remove_tab_from_empty_tabs", tabId: tab.id});
|
|
DOM_RefreshGUI();
|
|
tt.schedule_update_data++;
|
|
});
|
|
}
|
|
|
|
function Tabs_GetTabDepthInTree(Node) {
|
|
let Depth = 0;
|
|
let ParentNode = Node;
|
|
if (ParentNode == null) return Parents;
|
|
let Stop = false;
|
|
while (!Stop && ParentNode.parentNode != null) {
|
|
if (ParentNode.parentNode.classList != undefined) {
|
|
if (ParentNode.parentNode.classList.contains("tab")) Depth++;
|
|
if (ParentNode.parentNode.classList.contains("folder") || ParentNode.parentNode.classList.contains("group")) {
|
|
Stop = true;
|
|
} else {
|
|
ParentNode = ParentNode.parentNode;
|
|
}
|
|
} else {
|
|
Stop = true;
|
|
}
|
|
}
|
|
return Depth;
|
|
}
|
|
|
|
function Tabs_ActionClickTab(TabNode, bgOption) {
|
|
if (bgOption == "new_tab") {
|
|
let pin = TabNode.classList.contains("pin");
|
|
Tabs_OpenNewTab(pin, TabNode.id, undefined, undefined);
|
|
}
|
|
if (bgOption == "new_child_tab") {
|
|
let pin = TabNode.classList.contains("pin");
|
|
Tabs_OpenNewTab(pin, (pin ? TabNode.id : undefined), (pin ? undefined : TabNode.id), ((opt.append_child_tab === "bottom" || opt.append_child_tab === "after") ? true : false));
|
|
}
|
|
if (bgOption == "expand_collapse") DOM_EventExpandBox(TabNode);
|
|
if (bgOption == "close_tab") {
|
|
if ((TabNode.classList.contains("pin") && opt.allow_pin_close) || TabNode.classList.contains("tab")) Tabs_CloseTabs([parseInt(TabNode.id)]);
|
|
}
|
|
if (bgOption == "undo_close_tab") {
|
|
chrome.sessions.getRecentlyClosed(null, function(sessions) {
|
|
if (sessions.length > 0) chrome.sessions.restore(null, function(restored) {});
|
|
});
|
|
}
|
|
if (bgOption == "reload_tab") {chrome.tabs.reload(parseInt(TabNode.id));}
|
|
if (bgOption == "unload_tab") {
|
|
if (TabNode.classList.contains("active_tab")) {
|
|
Tabs_SwitchActiveTabBeforeClose(tt.active_group);
|
|
setTimeout(function() {Tabs_DiscardTabs([parseInt(TabNode.id)]);}, 500);
|
|
} else {
|
|
Tabs_DiscardTabs([parseInt(TabNode.id)]);
|
|
}
|
|
}
|
|
if (bgOption == "activate_previous_active" && TabNode.classList.contains("active_tab")) {
|
|
let PrevActiveTabId = parseInt(tt.groups[tt.active_group].prev_active_tab);
|
|
if (isNaN(PrevActiveTabId) == false) chrome.tabs.update(PrevActiveTabId, {active: true});
|
|
}
|
|
}
|
|
|
|
function Tabs_SetActiveTab(tabId, switchToGroup) {
|
|
if (opt.debug) Utils_log("f: SetActiveTab, tabId: " + tabId);
|
|
let Tab = document.getElementById(tabId);
|
|
if (Tab != null) {
|
|
let TabGroup = DOM_GetParentsByClass(Tab, "group");
|
|
if (TabGroup.length) {
|
|
if (Tab.classList.contains("tab")) Groups_SetActiveTabInGroup(TabGroup[0].id, tabId);
|
|
if (switchToGroup) Groups_SetActiveGroup(TabGroup[0].id, false, false); // not going to scroll, because mostly it's going to change to a new active in group AFTER switch, so we are not going to scroll to previous active tab
|
|
}
|
|
let active_tabs = document.querySelectorAll(".pin.active_tab, #" + tt.active_group + " .active_tab");
|
|
for (let s of active_tabs) {
|
|
DOM_SetClasses(s, [], ["active_tab"], []);
|
|
}
|
|
DOM_RemoveHighlight();
|
|
DOM_SetClasses(Tab, ["active_tab"], ["attention"], []);
|
|
if (tt.tabs[tabId]) tt.tabs[tabId].ScrollToTab();
|
|
}
|
|
}
|
|
|
|
function Tabs_SwitchActiveTabBeforeClose(ActiveGroupId) {
|
|
if (opt.debug) Utils_log("f: SwitchActiveTabBeforeClose");
|
|
let activeGroup = document.getElementById(ActiveGroupId);
|
|
if (document.querySelectorAll("#" + ActiveGroupId + " .tab:not(.will_be_closed)").length <= 1 && document.querySelector(".pin.active_tab") == null) { // CHECK IF CLOSING LAST TAB IN ACTIVE GROUP
|
|
let pins = document.querySelectorAll(".pin");
|
|
if (pins.length > 0) { // IF THERE ARE ANY PINNED TABS, ACTIVATE IT
|
|
if (opt.debug) Utils_log("available pin, switching to: " + pins[pins.length - 1].id);
|
|
chrome.tabs.update(parseInt(pins[pins.length - 1].id), {active: true});
|
|
return;
|
|
} else { // NO OTHER CHOICE BUT TO SEEK IN ANOTHER GROUP
|
|
if (opt.after_closing_active_tab == "above" || opt.after_closing_active_tab == "above_seek_in_parent") {
|
|
if (activeGroup.previousSibling != null) {
|
|
if (document.querySelectorAll("#" + activeGroup.previousSibling.id + " .tab").length > 0) {
|
|
Groups_SetActiveGroup(activeGroup.previousSibling.id, true, true);
|
|
} else {
|
|
Tabs_SwitchActiveTabBeforeClose(activeGroup.previousSibling.id);
|
|
return;
|
|
}
|
|
} else {
|
|
Groups_SetActiveGroup("tab_list", true, true);
|
|
}
|
|
} else {
|
|
if (activeGroup.nextSibling != null) {
|
|
if (document.querySelectorAll("#" + activeGroup.nextSibling.id + " .tab").length > 0) {
|
|
Groups_SetActiveGroup(activeGroup.nextSibling.id, true, true);
|
|
} else {
|
|
Tabs_SwitchActiveTabBeforeClose(activeGroup.nextSibling.id);
|
|
return;
|
|
}
|
|
} else {
|
|
Groups_SetActiveGroup("tab_list", true, true);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (opt.debug) Utils_log("available tabs in current group, switching option is: " + opt.after_closing_active_tab);
|
|
if (opt.after_closing_active_tab == "above") Tabs_ActivatePrevTab(true);
|
|
if (opt.after_closing_active_tab == "below") Tabs_ActivateNextTab(true);
|
|
if (opt.after_closing_active_tab == "above_seek_in_parent") Tabs_ActivatePrevTabSameLevel();
|
|
if (opt.after_closing_active_tab == "below_seek_in_parent") Tabs_ActivateNextTabSameLevel();
|
|
}
|
|
}
|
|
|
|
function Tabs_ActivateNextTabSameLevel() {
|
|
let activeTab = document.querySelector("#" + tt.active_group + " .tab.active_tab") != null ? document.querySelector("#" + tt.active_group + " .tab.active_tab") : document.querySelector(".pin.active_tab");
|
|
if (activeTab == null) return;
|
|
let NewActiveId;
|
|
let Node = activeTab;
|
|
if (activeTab.classList.contains("tab")) {
|
|
if (opt.promote_children && activeTab.childNodes[1].firstChild != null && activeTab.childNodes[1].firstChild.classList.contains("tab") && activeTab.childNodes[1].firstChild.classList.contains("will_be_closed") == false) NewActiveId = activeTab.childNodes[1].firstChild.id;
|
|
}
|
|
if (NewActiveId == undefined) {
|
|
while (NewActiveId == undefined && Node.nextSibling != null && Node.classList != undefined) {
|
|
if ((Node.nextSibling.classList.contains("pin") || Node.nextSibling.classList.contains("tab")) && Node.nextSibling.classList.contains("will_be_closed") == false) NewActiveId = Node.nextSibling.id;
|
|
Node = Node.nextSibling;
|
|
}
|
|
}
|
|
if (NewActiveId == undefined) {
|
|
while (NewActiveId == undefined && Node.previousSibling != null && Node.classList != undefined) {
|
|
if ((Node.previousSibling.classList.contains("pin") || Node.previousSibling.classList.contains("tab")) && Node.previousSibling.classList.contains("will_be_closed") == false) NewActiveId = Node.previousSibling.id;
|
|
Node = Node.previousSibling;
|
|
}
|
|
}
|
|
if (NewActiveId == undefined) {Tabs_ActivatePrevTab();}
|
|
if (NewActiveId != undefined) {
|
|
let tabId = parseInt(NewActiveId);
|
|
if (isNaN(tabId) == false) chrome.tabs.update(tabId, {active: true});
|
|
}
|
|
}
|
|
|
|
function Tabs_ActivatePrevTabSameLevel() {
|
|
let activeTab = document.querySelector("#" + tt.active_group + " .tab.active_tab") != null ? document.querySelector("#" + tt.active_group + " .tab.active_tab") : document.querySelector(".pin.active_tab");
|
|
if (activeTab == null) return;
|
|
let NewActiveId;
|
|
let Node = activeTab;
|
|
if (activeTab.classList.contains("tab")) {
|
|
if (opt.promote_children && activeTab.childNodes[1].firstChild != null && activeTab.childNodes[1].firstChild.classList.contains("tab") && activeTab.childNodes[1].firstChild.classList.contains("will_be_closed") == false) NewActiveId = activeTab.childNodes[1].firstChild.id;
|
|
}
|
|
if (NewActiveId == undefined) {
|
|
while (NewActiveId == undefined && Node.previousSibling != null && Node.classList != undefined) {
|
|
if ((Node.previousSibling.classList.contains("pin") || Node.previousSibling.classList.contains("tab")) && Node.previousSibling.classList.contains("will_be_closed") == false) NewActiveId = Node.previousSibling.id;
|
|
Node = Node.previousSibling;
|
|
}
|
|
}
|
|
if (NewActiveId == undefined) {
|
|
while (NewActiveId == undefined && Node.nextSibling != null && Node.classList != undefined) {
|
|
if ((Node.nextSibling.classList.contains("pin") || Node.nextSibling.classList.contains("tab")) && Node.nextSibling.classList.contains("will_be_closed") == false) NewActiveId = Node.nextSibling.id;
|
|
Node = Node.nextSibling;
|
|
}
|
|
}
|
|
if (NewActiveId == undefined) Tabs_ActivateNextTab();
|
|
if (NewActiveId != undefined) {
|
|
let tabId = parseInt(NewActiveId);
|
|
if (isNaN(tabId) == false) chrome.tabs.update(tabId, {active: true});
|
|
}
|
|
}
|
|
|
|
function Tabs_ActivateNextTab(allow_loop) {
|
|
let activeTab = document.querySelector("#" + tt.active_group + " .tab.active_tab") != null ? document.querySelector("#" + tt.active_group + " .tab.active_tab") : document.querySelector(".pin.active_tab");
|
|
if (activeTab == null) return;
|
|
let NewActiveId;
|
|
let Node = activeTab;
|
|
let parents = DOM_GetAllParents(activeTab);
|
|
while (Node != null && Node.classList != undefined) {
|
|
if (parents.indexOf(Node) == -1 && Node != activeTab && (Node.classList.contains("pin") || Node.classList.contains("tab")) && Node.classList.contains("will_be_closed") == false) {
|
|
NewActiveId = Node.id;
|
|
Node = null;
|
|
} else {
|
|
if (parents.indexOf(Node) == -1 && Node.childNodes[1] && Node.childNodes[1].classList.contains("children") && Node.childNodes[1].childNodes.length > 0 && Node.classList.contains("c") == false) { // GO TO CHILDREN
|
|
Node = Node.childNodes[1].firstChild;
|
|
} else {
|
|
if (Node.nextSibling) { // GO TO NEXT SIBLING
|
|
Node = Node.nextSibling;
|
|
} else { // GO UP TO PARENT
|
|
Node = Node.parentNode.parentNode;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (allow_loop && NewActiveId == undefined) {
|
|
let RestartLoopFromPin = document.querySelector(".pin");
|
|
let RestartLoopFromTab = document.querySelector("#°" + tt.active_group + " .tab");
|
|
if (activeTab.classList.contains("pin")) {
|
|
if (RestartLoopFromTab != null) {
|
|
NewActiveId = RestartLoopFromTab.id;
|
|
} else {
|
|
if (RestartLoopFromPin != null) NewActiveId = RestartLoopFromPin.id;
|
|
}
|
|
}
|
|
if (activeTab.classList.contains("tab")) {
|
|
if (RestartLoopFromPin != null) {
|
|
NewActiveId = RestartLoopFromPin.id;
|
|
} else {
|
|
if (RestartLoopFromTab != null) NewActiveId = RestartLoopFromTab.id;
|
|
}
|
|
}
|
|
}
|
|
if (NewActiveId != undefined) {
|
|
let tabId = parseInt(NewActiveId);
|
|
if (isNaN(tabId) == false) chrome.tabs.update(tabId, {active: true});
|
|
}
|
|
}
|
|
|
|
function Tabs_ActivatePrevTab(allow_loop) {
|
|
let activeTab = document.querySelector("#" + tt.active_group + " .tab.active_tab") != null ? document.querySelector("#" + tt.active_group + " .tab.active_tab") : document.querySelector(".pin.active_tab");
|
|
if (activeTab == null) return;
|
|
let NewActiveId;
|
|
let Node = activeTab;
|
|
while (Node != null && Node.classList != undefined) {
|
|
if (Node != activeTab && (Node.classList.contains("pin") || Node.classList.contains("tab")) && Node.classList.contains("will_be_closed") == false) {
|
|
NewActiveId = Node.id;
|
|
Node = null;
|
|
} else {
|
|
if (Node.previousSibling) { // GO TO PREV SIBLING
|
|
Node = Node.previousSibling;
|
|
while (Node != null && Node.classList != undefined && Node.childNodes[1] && Node.childNodes[1].classList.contains("children") && Node.childNodes[1].childNodes.length > 0 && Node.classList.contains("c") == false) {
|
|
Node = Node.childNodes[1].lastChild;
|
|
}
|
|
} else { // GO UP TO PARENT
|
|
Node = Node.parentNode.parentNode;
|
|
}
|
|
}
|
|
}
|
|
if (allow_loop && NewActiveId == undefined) {
|
|
let RestartLoopFromPin = document.querySelector(".pin:last-child");
|
|
let RestartLoopFromTab = document.querySelectorAll("#°" + tt.active_group + " .tab");
|
|
if (activeTab.classList.contains("pin")) {
|
|
if (RestartLoopFromTab.length > 0) {
|
|
NewActiveId = RestartLoopFromTab[RestartLoopFromTab.length - 1].id;
|
|
} else {
|
|
if (RestartLoopFromPin != null) NewActiveId = RestartLoopFromPin.id;
|
|
}
|
|
}
|
|
if (activeTab.classList.contains("tab")) {
|
|
if (RestartLoopFromPin != null) {
|
|
NewActiveId = RestartLoopFromPin.id;
|
|
} else {
|
|
if (RestartLoopFromTab != null) NewActiveId = RestartLoopFromTab[RestartLoopFromTab.length - 1].id;
|
|
}
|
|
}
|
|
}
|
|
if (NewActiveId != undefined) {
|
|
let tabId = parseInt(NewActiveId);
|
|
if (isNaN(tabId) == false) chrome.tabs.update(tabId, {active: true});
|
|
}
|
|
} |