1.8.7 release

This commit is contained in:
karol@jagiello.it 2018-12-13 23:55:34 +01:00
parent 6211e85683
commit 56b3bafe64
67 changed files with 10797 additions and 12527 deletions

View File

@ -1,19 +1,50 @@
WITH NEW API:
REDO SIDEBAR INITIALIZE ok!
RECHECK CLOSE TABS - activeTab query (works)
FINISH BACKGROUND LISTENERS (ORPHAN CASE) YAYYYYYY PROBABLY DONE!
FINISH EVENTS - DROP (MAYBE DONE?)
REDO START DRAG OF GROUP TAB AND FOLDER (MAYBE there)
REDO DRAG OVER PIN_LIST AND GROUP (DONE!)
REDO CloseTabs (looks fine, more testing needed)
RECHECK SetTabClass (looks fine, more testing needed)
FINISH BACKUP MERGE and recreate group and session, REDO load group, coooooz' not work (done, testing needed)
REDO DETACH TAB!!! (maybe done)
REVAMP MENU
REVAMP TOOLBAR FUNCTIONS
FIX ADD NEW FOLDER (from toolbar and from menu - add insertAfterID to new folder function)
REDO PROMOTE TABS IN LISTENERS IN: tab_removed AND tab_detached
ADD LINKS TO OPTIONS PAGE AND ADD RED COMMENTS
ADD PRESETS FOR OPTIONS
CHANGES:
1. shortcut to open TreeTabs Sidebar is now F1
2. log does not preserve any personal data (urls) for GDPR law
NEW:
1. you can now drag&drop entire group to another window
2. tree structure is tracked in background (excluded closing tabs)
3. added alt+w shortcut to close a tree of tabs
4. creating folder will now prompt for a new name
5. search for *audible, *muted, *unloaded, *loaded tabs! Just write *audible in search box!
1. mute icon config option (disable animation)
2. "TURN OFF DIMMING" OF AUDIO AND FOR ATTENTION
3. you can now drop folders between tabs, but only if root is folder or group
FIXES:
1. import window was not showing up
2. export group and export session had file extension in name
3. pin tree had bug in setting class
FIXED:
"Close other" doesn't respect pinned tabs.
@ -36,7 +67,6 @@ line for children hierarchy (like at the beggining)
return to the first tab with mousewheel when we are at the bottom list (loop) - "mousewheel scroll on the last tab allow to return to the first one"
mute icon config option (disable animation)
FIREFOX CONTAINERS
@ -102,7 +132,40 @@ Accept BCH (BitcoinCash) donations as the FEES make it FAR more palatable to don
- Like many other commenters suggested, it would be wonderful to see some indication of the container a tab was opened in, if any. Getting an option to directly be able to chose to open a new tab in a container would also be very useful.
Option to change the color of the icon indicating that a tab is a source of audio. (separated for playing and muted)
I DON'T UNDERSTAND THOSE FROM COMMENTS
- add possibility open all tabs in folder in new left tab group with deleting this folder;
- for economy memory your tabs must to makings (html code) during activating left tab group or during unfold folders/trees;
- real FF tabs must creating and linking only after activate your tabs;
- real FF tabs must creating and linking only after activate your tabs;

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"ToolbarShow":true,"ColorsSet":{"group_list_button_hover_background":"#000000","tab_list_background":"#1e1e1e","group_list_background":"#1e1e1e","attention_background":"#ffd6ce","pin_list_background":"#000000","tab_background":"#363d45","tab_hover_border":"#000000","tab_border":"#000000","tab_title_font_style":"normal","tab_title_font_color":"#b7b7b7","close_x":"#7d7d7d","tab_hover_background":"#717171","tab_hover_title_font_color":"#ffffff","tab_discarded_background":"#4c4c4c","tab_discarded_title_font_color":"#000000","tab_header_border_radius":"0px","children_padding_left":"7px","tab_discarded_border":"#4c4c4c","button_background":"#1e1e1e","toolbar_background":"#1e1e1e","button_on_background":"#808080","button_icons":"#808080","button_icons_hover":"#ffffff","button_on_icons":"#000000","button_border":"#1e1e1e","button_hover_border":"#808080","filter_box_font":"#ffffff","filter_box_background":"#000000","filter_box_border":"#000000","filter_clear_icon":"#ffffff","toolbar_shelf_background":"#1e1e1e","toolbar_border_bottom":"#808080","button_shelf_background":"#1e1e1e","button_shelf_border":"#1e1e1e","group_list_borders":"#323232"},"TabsSizeSetNumber":3,"TabsMargins":"2","theme_name":"DarkFox","theme_version":4}

View File

@ -0,0 +1 @@
{"ToolbarShow":true,"ColorsSet":{"tab_border":"#d2d2d2","tab_hover_border":"#797979","tab_discarded_hover_border":"#797979","tab_discarded_border":"#d2d2d2","tabs_menu_hover_border":"#d7d7d7","tabs_menu_hover_background":"#d7d7d7","close_hover_border":"#bfbfbf","tab_selected_border":"#70c0e7","tab_selected_hover_border":"#70c0e7","tab_active_border":"#70c0e7","tab_discarded_background":"#fafafa","tab_background":"#fafafa","tab_discarded_title_font_color":"#353535","tab_discarded_hover_title_font_color":"#353535","tab_selected_discarded_title_font_color":"#353535","tab_selected_discarded_hover_title_font_color":"#353535","tab_title_font_color":"#353535","tab_hover_title_font_color":"#353535","tab_selected_title_font_color":"#353535","tab_selected_hover_title_font_color":"#353535","tab_active_title_font_color":"#353535","tab_active_hover_title_font_color":"#353535","tab_active_selected_title_font_color":"#353535","tab_selected_active_hover_title_font_color":"#353535","tab_filtered_title_font_color":"#353535","tab_filtered_hover_title_font_color":"#353535","tab_filtered_active_title_font_color":"#353535","tab_filtered_active_hover_title_font_color":"#353535","tab_filtered_selected_title_font_color":"#353535","tab_filtered_selected_hover_title_font_color":"#353535","tab_filtered_selected_active_title_font_color":"#353535","tab_filtered_selected_active_hover_title_font_color":"#353535","tab_filtered_highlighted_search_title_font_color":"#353535","tab_filtered_highlighted_search_hover_title_font_color":"#353535","tab_filtered_active_highlighted_search_title_font_color":"#353535","tab_filtered_active_highlighted_search_hover_title_font_color":"#353535","tab_filtered_selected_highlighted_search_title_font_color":"#353535","tab_filtered_selected_highlighted_search_hover_title_font_color":"#353535","tab_filtered_selected_active_highlighted_search_title_font_color":"#353535","tab_filtered_selected_active_highlighted_search_hover_title_font_color":"#353535","tab_filtered_background":"#f8ea45","tab_filtered_active_background":"#f8ea45","tab_filtered_selected_background":"#b4e817","tab_filtered_selected_hover_background":"#96c113","tab_filtered_selected_active_background":"#b4e817","tab_filtered_selected_active_hover_background":"#96c113","tab_filtered_selected_hover_border":"#797979","tab_filtered_selected_active_hover_border":"#797979","tab_filtered_selected_border":"#797979","tab_filtered_selected_active_border":"#797979","tab_filtered_border":"#797979","tab_filtered_active_border":"#797979","tab_filtered_hover_border":"#797979","tab_filtered_active_hover_border":"#797979","tab_filtered_highlighted_search_background":"#ffa500","tab_filtered_highlighted_search_border":"#797979","tab_filtered_active_highlighted_search_border":"#797979","tab_filtered_active_highlighted_search_background":"#ffa500","tab_filtered_selected_highlighted_search_background":"#ffa500","tab_filtered_selected_highlighted_search_border":"#797979","tab_filtered_selected_active_highlighted_search_background":"#ffa500","tab_filtered_selected_active_highlighted_search_border":"#797979","tab_filtered_highlighted_search_hover_background":"#d78b00","tab_filtered_highlighted_search_hover_border":"#797979","tab_filtered_active_highlighted_search_hover_background":"#d78b00","tab_filtered_active_highlighted_search_hover_border":"#797979","tab_filtered_selected_highlighted_search_hover_background":"#d78b00","tab_filtered_selected_highlighted_search_hover_border":"#797979","tab_filtered_selected_active_highlighted_search_hover_background":"#d78b00","tab_filtered_selected_active_highlighted_search_hover_border":"#797979","children_padding_left":"13px","tab_list_background":"#fafafa","tab_selected_active_hover_title_font_style":"italic","tab_selected_active_hover_title_font_weight":"bold","tab_active_title_font_weight":"bold","tab_active_hover_title_font_weight":"bold","tab_hover_background":"#e6e6e6","tab_discarded_hover_background":"#e6e6e6","tab_header_border_radius":"0px","attention_background":"#ed1c24","attention_border":"#ed1c24","close_hover_x":"#ed1c24","close_hover_background":"#bfbfbf","close_x":"#7d7d7d","filter_box_font":"#353535"},"TabsSizeSetNumber":4,"TabsMargins":"0","theme_name":"Light and blue (by Compilenix)","theme_version":4}

View File

@ -0,0 +1 @@
{"ToolbarShow":true,"ColorsSet":{"children_padding_left":"9px","tab_header_border_radius":"2px","expand_closed_background":"#464646","folder_icon_open":"#282828","tab_background":"#343232","tab_discarded_background":"#343232","tab_discarded_border":"#000000","tab_active_background":"#3c3939","attention_background":"#2c2c2c","tab_list_background":"#343232","tab_border":"#000000","tab_active_border":"#000000","close_hover_background":"#504b4b","tab_active_title_font_weight":"normal","tab_hover_background":"#504b4b","tab_active_hover_background":"#504b4b","tab_discarded_hover_background":"#504b4b","tab_discarded_hover_border":"#000000","tab_hover_border":"#000000","tab_active_title_font_color":"#7e7e7e","tab_title_font_color":"#7e7e7e","tab_active_selected_title_font_color":"#7e7e7e","tab_active_hover_title_font_color":"#7e7e7e","tab_selected_active_hover_title_font_color":"#7e7e7e","tab_hover_title_font_color":"#7e7e7e","tab_selected_title_font_color":"#7e7e7e","tab_selected_hover_title_font_color":"#7e7e7e","tab_active_selected_background":"#343232","tab_selected_active_hover_background":"#343232","tab_selected_discarded_background":"#343232","tab_selected_discarded_hover_background":"#343232","tab_selected_background":"#423e3e","tab_selected_hover_background":"#3c3939","tab_selected_border":"#000000","tab_selected_hover_border":"#000000","tab_active_hover_border":"#000000","tab_active_selected_border":"#000000","tab_selected_active_hover_border":"#000000","tab_selected_discarded_border":"#000000","tab_selected_discarded_hover_border":"#000000","tabs_menu_background":"#343232","tabs_menu_font":"#7e7e7e","tabs_menu_separator":"#000000","drag_indicator":"#c0c0c0","tabs_menu_hover_border":"#000000","tabs_menu_border":"#000000","tabs_menu_hover_background":"#343232","pin_list_background":"#343232","filter_box_background":"#504b4b","toolbar_background":"#343232","toolbar_shelf_background":"#343232","button_shelf_background":"#343232","button_background":"#343232","button_on_background":"#504b4b","button_shelf_hover_background":"#504b4b","button_hover_background":"#504b4b","button_border":"#343232","filter_box_border":"#343232","toolbar_border_bottom":"#343232","button_shelf_border":"#343232","button_shelf_hover_border":"#000000","button_hover_border":"#000000","group_list_button_hover_background":"#504b4b","group_list_background":"#343232","group_list_default_font_color":"#808080","group_list_borders":"#000000","close_hover_border":"#504b4b","tab_active_hover_title_font_weight":"normal","tab_active_selected_title_font_weight":"normal","tab_selected_active_hover_title_font_weight":"normal","expand_hover_background":"#ffffff","expand_open_background":"#919191"},"TabsSizeSetNumber":3,"TabsMargins":"0","theme_name":"Quantum","theme_version":4}

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@
"manifest_version": 2,
"default_locale": "en",
"background": {
"scripts": [ "listeners_bg.js", "scripts/common.js", "background.js" ],
"scripts": [ "global.js", "./scripts/preferences.js", "background_firefox.js", "background_opera.js", "background_vivaldi.js", "background.js" ],
"persistent": true
},
"name": "Tree Tabs",
@ -36,7 +36,7 @@
}
},
"options_ui": {
"page": "options.html",
"page": "options/options.html",
"open_in_tab": true
},
"commands": {
@ -45,5 +45,5 @@
"description": "close tree"
}
},
"version": "100"
"version": "1.8.6"
}

View File

@ -2,7 +2,7 @@
"manifest_version": 2,
"default_locale": "en",
"background": {
"scripts": [ "listeners_bg.js", "scripts/common.js", "background.js" ],
"scripts": [ "global.js", "./scripts/preferences.js", "background_firefox.js", "background_opera.js", "background_vivaldi.js", "background.js" ],
"persistent": true
},
"name": "Tree Tabs",
@ -41,12 +41,12 @@
"applications": {
"gecko": {
"id": "TreeTabs@jagiello.it",
"strict_min_version": "57.0"
"strict_min_version": "63.0"
}
},
"options_ui": {
"page": "options.html",
"page": "options/options.html",
"open_in_tab": true
},
"version": "1.7.2"
"version": "1.8.7"
}

View File

@ -3,7 +3,7 @@
"minimum_opera_version": "42",
"default_locale": "en",
"background": {
"scripts": [ "listeners_bg.js", "scripts/common.js", "background.js" ],
"scripts": [ "global.js", "./scripts/preferences.js", "background_firefox.js", "background_opera.js", "background_vivaldi.js", "background.js" ],
"persistent": true
},
"name": "Tree Tabs",
@ -24,12 +24,12 @@
"default_panel": "sidebar.html",
"default_title": "Tree Tabs"
},
"options_page": "options.html",
"options_page": "options/options.html",
"commands": {
"close_tree": {
"suggested_key": { "default": "Alt+W" },
"description": "close tree"
}
},
"version": "1.7.2"
"version": "1.8.6"
}

View File

@ -2,7 +2,7 @@
"manifest_version": 2,
"default_locale": "en",
"background": {
"scripts": [ "listeners_bg.js", "scripts/common.js", "background.js" ],
"scripts": [ "global.js", "./scripts/preferences.js", "background_firefox.js", "background_opera.js", "background_vivaldi.js", "background.js" ],
"persistent": true
},
"name": "Tree Tabs",
@ -16,7 +16,7 @@
},
"permissions": [ "tabs", "sessions", "<all_urls>", "storage", "unlimitedStorage", "bookmarks" ],
"options_ui": {
"page": "options.html",
"page": "options/options.html",
"open_in_tab": false
},
"commands": {
@ -25,5 +25,5 @@
"description": "close tree"
}
},
"version": "1.7.2"
"version": "1.8.6"
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

335
background_firefox.js Normal file
View File

@ -0,0 +1,335 @@
// QUANTUM
function QuantumStart() {
chrome.storage.local.get(null, function(storage) {
chrome.windows.getAll({ windowTypes: ["normal"], populate: true }, function(w) {
let windows_data = {};
let tabs_data = {};
for (let win of w) {
Promise.resolve(browser.sessions.getWindowValue(win.id, "TTdata")).then(function(WindowData) {
windows_data[win.id] = WindowData;
for (let tab of win.tabs) {
Promise.resolve(browser.sessions.getTabValue(tab.id, "TTdata")).then(function(TData) {
if (TData != undefined) b.tt_ids[TData.ttid] = tab.id;
tabs_data[tab.id] = TData;
});
}
});
}
setTimeout(function() {
// LOAD PREFERENCES
Preferences_GetCurrentPreferences(storage);
// CACHED COUNTS AND STUFF
let tabs_matched = 0;
let tabs_count = 0;
for (let win of w) {
tabs_count += win.tabs.length;
}
let lastWinId = w[w.length - 1].id;
let lastTabId = w[w.length - 1].tabs[w[w.length - 1].tabs.length - 1].id;
if (opt.debug == true) {
if (storage.debug_log != undefined) b.debug = storage.debug_log;
// if (retry == 0) pushlog("TreeTabs background start");
}
for (let win of w) {
// LOAD TTID FROM FIREFOX GET WINDOW VALUE
if (opt.skip_load == false && windows_data[win.id] != undefined) {
b.windows[win.id] = Object.assign({}, windows_data[win.id]);
} else {
QuantumAppendWinTTId(win.id);
}
for (let tab of win.tabs) {
// LOAD TTID FROM FIREFOX GET TAB VALUE
if (opt.skip_load == false && tabs_data[tab.id] != undefined) {
b.tabs[tab.id] = Object.assign({}, tabs_data[tab.id]);
tabs_matched++;
if (tabs_data[tab.id].parent_ttid != undefined && tabs_data[tab.id].parent_ttid != "") { // legacy
b.tabs[tab.id].parent = tabs_data[tab.id].parent_ttid; // legacy
delete b.tabs[tab.id].parent_ttid; // legacy
} // legacy
} else {
QuantumAppendTabTTId(tab);
}
if (tab.active) b.windows[win.id].activeTabId = tab.id;
}
}
// OK, DONE, NOW REPLACE OLD PARENTS IDS WITH THIS SESSION IDS
for (let tabId in b.tabs) {
if (b.tt_ids[b.tabs[tabId].parent] != undefined) {
b.tabs[tabId].parent = b.tt_ids[b.tabs[tabId].parent]; // is tab
} else {
b.tabs[tabId].parent = b.tabs[tabId].parent; // is not tab
}
}
// OK, SAME THING FOR ACTIVE TABS IN GROUPS
for (let winId in b.windows) {
for (let group in b.windows[winId].groups) {
if (b.tt_ids[b.windows[winId].groups[group].active_tab] != undefined) b.windows[winId].groups[group].active_tab = b.tt_ids[b.windows[winId].groups[group].active_tab];
if (b.tt_ids[b.windows[winId].groups[group].prev_active_tab] != undefined) b.windows[winId].groups[group].prev_active_tab = b.tt_ids[b.windows[winId].groups[group].prev_active_tab];
}
}
if (opt.skip_load == false && tabs_matched < tabs_count*0.5) {
b.safe_mode = true;
SafeModeCheck();
// SAFE MODE IS DISABLED AFTER 10 MINUTES
setTimeout(function() {
b.safe_mode = false;
}, 600000);
if (opt.debug) pushlog("started in safe mode");
}
b.bg_running = true;
QuantumAutoSaveData();
QuantumStartListeners();
delete DefaultToolbar;
delete DefaultTheme;
delete DefaultPreferences;
delete DefaultMenu;
chrome.runtime.sendMessage({ command: "bg_started" });
if (opt.debug) pushlog("QuantumStart, Current windows count is: " + w.length + "Current tabs count is: " + tabs_count + "Matching tabs: " + tabs_matched);
}, 1000);
});
});
}
// save every second if there is anything to save obviously
async function QuantumAutoSaveData() {
setInterval(function() {
if (b.schedule_save > 1) b.schedule_save = 1;
if (b.safe_mode == false && b.bg_running && b.schedule_save > 0 && Object.keys(b.tabs).length > 1) {
chrome.windows.getAll({ windowTypes: ['normal'], populate: true }, function(w) {
for (let win of w) {
if (b.windows[win.id] != undefined) {
if (b.windows[win.id].ttid != undefined && b.windows[win.id].group_bar != undefined && b.windows[win.id].search_filter != undefined && b.windows[win.id].active_shelf != undefined && b.windows[win.id].active_group != undefined && b.windows[win.id].groups != undefined && b.windows[win.id].folders != undefined) {
let windowData = Object.assign({}, b.windows[win.id]);
for (let groupId in b.windows[win.id].groups) {
if (b.tabs[b.windows[win.id].groups[groupId].active_tab]) windowData.groups[groupId].active_tab = b.tabs[b.windows[win.id].groups[groupId].active_tab].ttid;
if (b.tabs[b.windows[win.id].groups[groupId].prev_active_tab]) windowData.groups[groupId].prev_active_tab = b.tabs[b.windows[win.id].groups[groupId].prev_active_tab].ttid;
}
browser.sessions.setWindowValue(win.id, "TTdata", windowData);
}
} else {
QuantumAppendWinTTId(win.id);
}
for (let tab of win.tabs) {
if (b.tabs[tab.id] != undefined) {
if (b.tabs[tab.id].ttid != undefined && b.tabs[tab.id].parent != undefined && b.tabs[tab.id].index != undefined && b.tabs[tab.id].expand != undefined) {
browser.sessions.setTabValue(tab.id, "TTdata", { ttid: b.tabs[tab.id].ttid, parent: (b.tabs[b.tabs[tab.id].parent] ? b.tabs[b.tabs[tab.id].parent].ttid : b.tabs[tab.id].parent), index: b.tabs[tab.id].index, expand: b.tabs[tab.id].expand });
} else {
QuantumAppendTabTTId(tab);
}
}
}
}
b.schedule_save--;
});
}
if (opt.debug == true) chrome.storage.local.set({ debug_log: b.debug });
}, 1000);
}
function QuantumGenerateNewWindowID() {
let newID = "";
while (newID == "") {
newID = "w_" + GenerateRandomID();
for (let wId in b.windows) {
if (wId == newID) newID = "";
}
}
return newID;
}
function QuantumGenerateNewTabID() {
let newID = "";
while (newID == "") {
newID = "t_" + GenerateRandomID();
for (let tId in b.tabs) {
if (tId == newID) newID = "";
}
}
return newID;
}
function QuantumAppendTabTTId(tab) {
let NewTTTabId = QuantumGenerateNewTabID();
if (b.tabs[tab.id] != undefined) {
b.tabs[tab.id].ttid = NewTTTabId;
} else {
b.tabs[tab.id] = { ttid: NewTTTabId, parent: (b.windows[tab.windowId] ? b.windows[tab.windowId].active_group : "tab_list"), index: tab.index, expand: "" };
}
b.tt_ids[NewTTTabId] = tab.id;
return NewTTTabId;
}
function QuantumAppendWinTTId(windowId) {
let NewTTWindowId = QuantumGenerateNewWindowID();
if (b.windows[windowId] != undefined) {
b.windows[windowId].ttid = NewTTWindowId;
} else {
b.windows[windowId] = { activeTabId: 0, ttid: NewTTWindowId, group_bar: opt.groups_toolbar_default, search_filter: "url", active_shelf: "", active_group: "tab_list", groups: { tab_list: { id: "tab_list", index: 0, active_tab: 0, prev_active_tab: 0, name: labels.ungrouped_group, font: "" } }, folders: {} };
}
}
function QuantumStartListeners() {
browser.browserAction.onClicked.addListener(function() {
browser.sidebarAction.setPanel({ panel: (browser.extension.getURL("/sidebar.html")) });
browser.sidebarAction.open();
});
chrome.tabs.onCreated.addListener(function(tab) {
if (b.windows[tab.windowId] == undefined) {
QuantumAppendWinTTId(tab.windowId);
}
let prevActiveTabId = b.windows[tab.windowId].activeTabId;
let t = Promise.resolve(browser.sessions.getTabValue(tab.id, "TTdata")).then(function(TabData) {
if (TabData != undefined) {
b.tabs[tab.id] = Object.assign({}, TabData);
let originalParent = b.tt_ids[TabData.parent] ? b.tt_ids[TabData.parent] : TabData.parent;
let AfterId = undefined;
let append = undefined;
if (originalParent) {
let originalParentChildren = GetChildren(b.tabs, originalParent);
if (TabData.index > 0 && TabData.index < originalParentChildren.length) {
for (let i = TabData.index + 1; i < originalParentChildren.length; i++) { // shift next siblings indexes
b.tabs[originalParentChildren[i]].index += 1;
}
AfterId = originalParentChildren[TabData.index];
}
if (TabData.index == 0) {
append = false;
}
if (TabData.index > originalParentChildren.length) {
append = true;
}
}
chrome.runtime.sendMessage({ command: "tab_created", windowId: tab.windowId, tabId: tab.id, tab: tab, ParentId: originalParent, InsertAfterId: AfterId, Append: append });
} else {
QuantumAppendTabTTId(tab);
chrome.tabs.get(tab.id, function(NewTab) { // get tab again as reported tab's url is empty! Also for some reason firefox sends tab with "active == false" even if tab is active (THIS IS POSSIBLY A NEW BUG IN FF 60!)
if (NewTab) {
OnMessageTabCreated(NewTab, prevActiveTabId);
}
});
}
});
});
chrome.tabs.onAttached.addListener(function(tabId, attachInfo) {
let oldId = tabId;
chrome.tabs.get(oldId, function(tab) {
ReplaceParents(oldId, tab.id);
chrome.runtime.sendMessage({ command: "tab_attached", windowId: attachInfo.newWindowId, tab: tab, tabId: tab.id, ParentId: b.tabs[tab.id].parent });
b.schedule_save++;
});
});
chrome.tabs.onDetached.addListener(function(tabId, detachInfo) {
chrome.runtime.sendMessage({ command: "tab_detached", windowId: detachInfo.oldWindowId, tabId: tabId });
});
chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) {
// if (b.windows[removeInfo.windowId].activeTabId == tabId) {
// chrome.runtime.sendMessage({command: "switch_active_tab", windowId: removeInfo.windowId, tabId: tabId});
// }
let SiblingTabs = GetChildren(b.tabs, b.tabs[tabId].parent);
let SiblingFolders = GetChildren(b.windows[removeInfo.windowId].folders, b.tabs[tabId].parent);
UnshiftChildrenIndexes(SiblingTabs, b.tabs[tabId].index, SiblingFolders, removeInfo.windowId);
if (b.EmptyTabs.indexOf(tabId) != -1) {
b.EmptyTabs.splice(b.EmptyTabs.indexOf(tabId), 1);
}
setTimeout(function() {
chrome.runtime.sendMessage({ command: "tab_removed", windowId: removeInfo.windowId, tabId: tabId });
}, 5);
delete b.tabs[tabId];
b.schedule_save++;
});
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (changeInfo.pinned == true) {
if (b.tabs[tabId]) {
b.tabs[tabId].parent = "pin_list";
b.schedule_save++;
}
}
if (changeInfo.pinned == false) {
if (b.tabs[tabId]) {
b.tabs[tabId].parent = "tab_list";
b.schedule_save++;
}
}
if (changeInfo.url != undefined) { // if set to append when url changes and matches pre-set group
if (tab.pinned == false) {
if (opt.move_tabs_on_url_change == "always" || ((opt.move_tabs_on_url_change == "from_empty" || opt.move_tabs_on_url_change == "from_empty_b") && b.EmptyTabs.indexOf(tabId) != -1)) {
AppendTabToGroupOnRegexMatch(tabId, tab.windowId, changeInfo.url);
}
}
if (changeInfo.url != b.newTabUrl && b.EmptyTabs.indexOf(tabId) != -1) {
b.EmptyTabs.splice(b.EmptyTabs.indexOf(tabId), 1);
}
}
if (changeInfo.title != undefined && !tab.active) {
chrome.runtime.sendMessage({ command: "tab_attention", windowId: tab.windowId, tabId: tabId });
}
chrome.runtime.sendMessage({ command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tabId, changeInfo: changeInfo });
});
chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId) {
chrome.tabs.get(addedTabId, function(tab) {
if (addedTabId == removedTabId) {
chrome.runtime.sendMessage({ command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tab.id, changeInfo: { status: tab.status, url: tab.url, title: tab.title, audible: tab.audible, mutedInfo: tab.mutedInfo } });
} else {
if (b.tabs[removedTabId]) {
b.tabs[addedTabId] = b.tabs[removedTabId];
}
ReplaceParents(tabId, tab.id);
chrome.runtime.sendMessage({ command: "tab_removed", windowId: tab.windowId, tabId: removedTabId });
chrome.runtime.sendMessage({ command: "tab_attached", windowId: tab.windowId, tab: tab, tabId: addedTabId, ParentId: b.tabs[addedTabId].parent });
// delete ttid[b.tabs[removedTabId].ttid];
// delete b.tabs[removedTabId];
}
setTimeout(function() {
QuantumAppendTabTTId(tab);
b.schedule_save++;
}, 100);
});
});
chrome.tabs.onActivated.addListener(function(activeInfo) {
if (b.windows[activeInfo.windowId]) {
b.windows[activeInfo.windowId].activeTabId = activeInfo.tabId;
}
chrome.runtime.sendMessage({ command: "tab_activated", windowId: activeInfo.windowId, tabId: activeInfo.tabId });
b.schedule_save++;
});
chrome.windows.onCreated.addListener(function(window) {
let win = Promise.resolve(browser.sessions.getWindowValue(window.id, "TTdata")).then(function(WindowData) {
if (WindowData != undefined) {
b.windows[window.id] = Object.assign({}, WindowData);
} else {
QuantumAppendWinTTId(window.id);
}
b.schedule_save++;
});
});
chrome.windows.onRemoved.addListener(function(windowId) {
delete b.windows[windowId];
b.schedule_save++;
});
}

266
background_opera.js Normal file
View File

@ -0,0 +1,266 @@
// OPERA
function OperaStart() {
chrome.windows.getAll({ windowTypes: ['normal'], populate: true }, function(w) {
chrome.storage.local.get(null, function(storage) {
// LOAD PREFERENCES
Preferences_GetCurrentPreferences(storage);
// load tabs and windows from storage
let refTabs = {};
let refWins = {};
let tabs_matched = 0;
let LoadedWindows = storage.windows ? storage.windows : [];
let LoadedTabs = storage.tabs ? storage.tabs : [];
let CurrentTabsCount = 0;
for (let win of w) {
CurrentTabsCount += win.tabs.length;
}
if (opt.debug == true) {
if (storage.debug_log != undefined) b.debug = storage.debug_log;
// if (retry == 0) pushlog("TreeTabs background start");
}
for (let win of w) {
if (win.tabs[0].url != "chrome://videopopout/") { // this is for opera for their extra video popup, which is weirdly queried as a "normal" window
let url1 = win.tabs[0].url;
let url2 = win.tabs[win.tabs.length - 1].url;
OperaAddWindowData(win.id);
if (opt.skip_load == false) {
for (let loadedWin of LoadedWindows) {
if ((loadedWin.url1 == url1 || loadedWin.url2 == url2) && refWins[loadedWin.id] == undefined) {
refWins[loadedWin.id] = win.id;
if (loadedWin.group_bar) b.windows[win.id].group_bar = loadedWin.group_bar;
if (loadedWin.search_filter) b.windows[win.id].search_filter = loadedWin.search_filter;
if (loadedWin.active_shelf) b.windows[win.id].active_shelf = loadedWin.active_shelf;
if (loadedWin.active_group) b.windows[win.id].active_group = loadedWin.active_group;
if (Object.keys(loadedWin.groups).length > 0) b.windows[win.id].groups = Object.assign({}, loadedWin.groups);
if (Object.keys(loadedWin.folders).length > 0) b.windows[win.id].folders = Object.assign({}, loadedWin.folders);
break;
}
}
}
}
}
// add new hashes for current tabs
for (let win of w) {
for (let tab of win.tabs) {
OperaHashURL(tab);
if (tab.active) b.windows[win.id].activeTabId = tab.id;
}
}
// compare saved tabs from storage to current session tabs, but can be skipped if set in options
if (opt.skip_load == false && LoadedTabs.length > 0) {
for (let win of w) {
for (tab of win.tabs) {
for (let loadedTab of LoadedTabs) {
if (loadedTab.hash == b.tabs[tab.id].hash && refTabs[loadedTab.id] == undefined) {
refTabs[loadedTab.id] = tab.id;
if (loadedTab.parent) b.tabs[tab.id].parent = loadedTab.parent;
if (loadedTab.index) b.tabs[tab.id].index = loadedTab.index;
if (loadedTab.expand) b.tabs[tab.id].expand = loadedTab.expand;
tabs_matched++;
break;
}
}
}
}
// replace parents tabIds for new ones, for that purpose refTabs was made before
for (let tabId in b.tabs) {
if (refTabs[b.tabs[tabId].parent] != undefined) b.tabs[tabId].parent = refTabs[b.tabs[tabId].parent];
}
// replace active tab ids for each group using refTabs
for (let windowId in b.windows) {
for (let group in b.windows[windowId].groups) {
if (refTabs[b.windows[windowId].groups[group].active_tab]) b.windows[windowId].groups[group].active_tab = refTabs[b.windows[windowId].groups[group].active_tab];
if (refTabs[b.windows[windowId].groups[group].prev_active_tab]) b.windows[windowId].groups[group].prev_active_tab = refTabs[b.windows[windowId].groups[group].prev_active_tab];
}
}
}
if (opt.skip_load == false && tabs_matched < LoadedTabs.length*0.5) {
b.safe_mode = true;
SafeModeCheck();
if (opt.debug) pushlog("started in safe mode");
if (storage.recovered_BAK) {
chrome.storage.local.set({ tabs: storage["tabs_BAK"+storage.recovered_BAK] });
chrome.storage.local.set({ windows: storage["windows_BAK"+storage.recovered_BAK] });
if (storage.recovered_BAK == 3) {
chrome.storage.local.remove("recovered_BAK");
} else {
chrome.storage.local.set({ recovered_BAK: (storage.recovered_BAK+1) });
}
} else {
chrome.storage.local.set({ recovered_BAK: 1 });
}
} else {
chrome.storage.local.remove("recovered_BAK");
}
if (opt.debug) pushlog("OperaStart, Current windows count is: " + w.length + "Saved windows count is: " + LoadedWindows.length + "Current tabs count is: " + CurrentTabsCount + "Loaded tabs count is: " + LoadedTabs.length + "Matching tabs: " + tabs_matched);
b.bg_running = true;
OperaAutoSaveData(0, 1000);
OperaAutoSaveData(1, 300000);
OperaAutoSaveData(2, 600000);
OperaAutoSaveData(3, 1800000);
OperaStartListeners();
delete DefaultToolbar;
delete DefaultTheme;
delete DefaultPreferences;
delete DefaultMenu;
chrome.runtime.sendMessage({ command: "bg_started" });
});
});
}
async function OperaAutoSaveData(BAK, LoopTimer) {
setInterval(function() {
if (b.schedule_save > 1 || BAK > 0) {
b.schedule_save = 1;
}
if (b.bg_running && b.schedule_save > 0 && Object.keys(b.tabs).length > 1) {
chrome.windows.getAll({ windowTypes: ['normal'], populate: true }, function(w) {
let Windows = [];
let Tabs = [];
for (let win of w) {
if (b.windows[win.id] != undefined) {
if (b.windows[win.id].group_bar != undefined && b.windows[win.id].search_filter != undefined && b.windows[win.id].active_shelf != undefined && b.windows[win.id].active_group != undefined && b.windows[win.id].groups != undefined && b.windows[win.id].folders != undefined) {
Windows.push({ url1: win.tabs[0].url, url2: win.tabs[win.tabs.length - 1].url, group_bar: b.windows[win.id].group_bar, search_filter: b.windows[win.id].search_filter, active_shelf: b.windows[win.id].active_shelf, active_group: b.windows[win.id].active_group, groups: b.windows[win.id].groups, folders: b.windows[win.id].folders });
}
} else {
OperaAddWindowData(win.id);
}
for (let tab of win.tabs) {
if (b.tabs[tab.id] != undefined) {
if (b.tabs[tab.id].hash != undefined && b.tabs[tab.id].parent != undefined && b.tabs[tab.id].index != undefined && b.tabs[tab.id].expand != undefined) {
Tabs.push({ id: tab.id, hash: b.tabs[tab.id].hash, parent: b.tabs[tab.id].parent, index: b.tabs[tab.id].index, expand: b.tabs[tab.id].expand });
}
} else {
OperaHashURL(tab);
}
}
}
chrome.storage.local.set((BAK == 0 ? { windows: Windows, tabs: Tabs } : (BAK == 1 ? { windows_BAK1: Windows, tabs_BAK1: Tabs } : (BAK == 2 ? { windows_BAK2: Windows, tabs_BAK2: Tabs } : { windows_BAK3: Windows, tabs_BAK3: Tabs }))));
b.schedule_save--;
});
}
if (opt.debug == true) chrome.storage.local.set({ debug_log: b.debug });
}, LoopTimer);
}
function OperaAddWindowData(winId) {
b.windows[winId] = { activeTabId: 0, group_bar: opt.groups_toolbar_default, search_filter: "url", active_shelf: "", active_group: "tab_list", groups: { tab_list: { id: "tab_list", index: 0, active_tab: 0, prev_active_tab: 0, name: labels.ungrouped_group, font: "" } }, folders: {} };
}
function OperaHashURL(tab) {
if (b.tabs[tab.id] == undefined) b.tabs[tab.id] = { hash: 0, parent: tab.pinned ? "pin_list" : (b.windows[tab.windowId] ? b.windows[tab.windowId].active_group : "tab_list"), index: (Object.keys(b.tabs).length + 1), expand: "n" };
let hash = 0;
for (let charIndex = 0; charIndex < tab.url.length; charIndex++) {
hash += tab.url.charCodeAt(charIndex);
}
b.tabs[tab.id].hash = hash;
}
function OperaStartListeners() { // start all listeners
chrome.tabs.onCreated.addListener(function(tab) {
if (b.windows[tab.windowId] == undefined) {
OperaAddWindowData(tab.windowId);
}
let prevActiveTabId = b.windows[tab.windowId].activeTabId;
OperaHashURL(tab);
OnMessageTabCreated(tab, prevActiveTabId);
});
chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) {
let SiblingTabs = GetChildren(b.tabs, b.tabs[tabId].parent);
let SiblingFolders = GetChildren(b.windows[removeInfo.windowId].folders, b.tabs[tabId].parent);
UnshiftChildrenIndexes(SiblingTabs, b.tabs[tabId].index, SiblingFolders, removeInfo.windowId);
if (b.EmptyTabs.indexOf(tabId) != -1) {
b.EmptyTabs.splice(b.EmptyTabs.indexOf(tabId), 1);
}
setTimeout(function() { chrome.runtime.sendMessage({ command: "tab_removed", windowId: removeInfo.windowId, tabId: tabId }); }, 5);
delete b.tabs[tabId];
b.schedule_save++;
});
chrome.tabs.onAttached.addListener(function(tabId, attachInfo) {
chrome.tabs.get(tabId, function(tab) {
chrome.runtime.sendMessage({ command: "tab_attached", windowId: attachInfo.newWindowId, tab: tab, tabId: tabId, ParentId: b.tabs[tabId].parent });
});
b.schedule_save++;
});
chrome.tabs.onDetached.addListener(function(tabId, detachInfo) {
chrome.runtime.sendMessage({ command: "tab_detached", windowId: detachInfo.oldWindowId, tabId: tabId });
b.schedule_save++;
});
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (b.tabs[tabId] == undefined || changeInfo.url != undefined) {
OperaHashURL(tab);
}
if (changeInfo.pinned != undefined) {
if (changeInfo.pinned == true) {
b.tabs[tabId].parent = "pin_list";
}
if (changeInfo.pinned == false) {
b.tabs[tabId].parent = "tab_list";
}
b.schedule_save++;
}
if (changeInfo.url != undefined) { // if set to append when url changes and matches pre-set group
if (tab.pinned == false) {
if (opt.move_tabs_on_url_change == "always" || ((opt.move_tabs_on_url_change == "from_empty" || opt.move_tabs_on_url_change == "from_empty_b") && b.EmptyTabs.indexOf(tabId) != -1)) {
AppendTabToGroupOnRegexMatch(tabId, tab.windowId, changeInfo.url);
}
}
if (changeInfo.url != b.newTabUrl && b.EmptyTabs.indexOf(tabId) != -1) {
b.EmptyTabs.splice(b.EmptyTabs.indexOf(tabId), 1);
}
}
if (changeInfo.title != undefined && !tab.active) {
chrome.runtime.sendMessage({ command: "tab_attention", windowId: tab.windowId, tabId: tabId });
}
chrome.runtime.sendMessage({ command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tabId, changeInfo: changeInfo });
});
chrome.tabs.onMoved.addListener(function(tabId, moveInfo) {
b.schedule_save++;
});
chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId) {
chrome.tabs.get(addedTabId, function(tab) {
if (addedTabId == removedTabId) {
chrome.runtime.sendMessage({ command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tab.id, changeInfo: { status: tab.status, url: tab.url, title: tab.title, audible: tab.audible, mutedInfo: tab.mutedInfo } });
} else {
ReplaceParents(tabId, tab.id);
if (b.tabs[removedTabId]) {
b.tabs[addedTabId] = b.tabs[removedTabId];
} else {
OperaHashURL(tab);
}
chrome.runtime.sendMessage({ command: "tab_removed", windowId: tab.windowId, tabId: removedTabId });
chrome.runtime.sendMessage({ command: "tab_attached", windowId: tab.windowId, tab: tab, tabId: addedTabId });
delete b.tabs[removedTabId];
}
b.schedule_save++;
});
});
chrome.tabs.onActivated.addListener(function(activeInfo) {
if (b.windows[activeInfo.windowId]) {
b.windows[activeInfo.windowId].activeTabId = activeInfo.tabId;
}
chrome.runtime.sendMessage({ command: "tab_activated", windowId: activeInfo.windowId, tabId: activeInfo.tabId });
b.schedule_save++;
});
chrome.windows.onCreated.addListener(function(window) {
OperaAddWindowData(window.id);
// b.windows[window.id] = {group_bar: opt.groups_toolbar_default, search_filter: "url", active_shelf: "", active_group: "tab_list", groups: {tab_list: {id: "tab_list", index: 0, active_tab: 0, prev_active_tab: 0, name: labels.ungrouped_group, font: ""}}, folders: {}};
b.schedule_save++;
});
chrome.windows.onRemoved.addListener(function(windowId) {
delete b.windows[windowId];
b.schedule_save++;
});
chrome.runtime.onSuspend.addListener(function() {
b.bg_running = false;
});
}

377
background_vivaldi.js Normal file
View File

@ -0,0 +1,377 @@
// VIVALDI
function VivaldiLegacyAddWindowData(win) {
b.windows[win.id] = { activeTabId: 0, group_bar: opt.groups_toolbar_default, search_filter: "url", active_shelf: "", active_group: "tab_list", groups: { tab_list: { id: "tab_list", index: 0, active_tab: 0, prev_active_tab: 0, name: labels.ungrouped_group, font: "" } }, folders: {} };
}
function VivaldiLegacyHashURL(tab) {
if (b.tabs[tab.id] == undefined) { b.tabs[tab.id] = { hash: 0, parent: tab.pinned ? "pin_list" : (b.windows[tab.windowId] ? b.windows[tab.windowId].active_group : "tab_list"), index: (Object.keys(b.tabs).length + 1), expand: "n" }; }
let hash = 0;
for (let charIndex = 0; charIndex < tab.url.length; charIndex++) {
hash += tab.url.charCodeAt(charIndex);
}
b.tabs[tab.id].hash = hash;
}
function VivaldiStart() {
chrome.windows.getAll({ windowTypes: ['normal'], populate: true }, function(w) {
chrome.storage.local.get(null, function(storage) {
// LOAD PREFERENCES
Preferences_GetCurrentPreferences(storage);
// LEGACY START TO CONVERT DATA
if ((storage.data_version == undefined && storage.tabs != undefined) || storage.data_version < 2) {
b.safe_mode = true;
let refTabs = {};
let refWins = {};
let tabs_matched = 0;
let LoadedWindows = storage.windows ? storage.windows : [];
let LoadedTabs = storage.tabs ? storage.tabs : [];
let CurrentTabsCount = 0;
for (let win of w) {
CurrentTabsCount += win.tabs.length;
}
for (let win of w) {
let url1 = win.tabs[0].url;
let url2 = win.tabs[win.tabs.length - 1].url;
VivaldiLegacyAddWindowData(win);
if (opt.skip_load == false) {
for (let loadedWin of LoadedWindows) {
if ((loadedWin.url1 == url1 || loadedWin.url2 == url2) && refWins[loadedWin.id] == undefined) {
refWins[loadedWin.id] = win.id;
if (loadedWin.group_bar) b.windows[win.id].group_bar = loadedWin.group_bar;
if (loadedWin.search_filter) b.windows[win.id].search_filter = loadedWin.search_filter;
if (loadedWin.active_shelf) b.windows[win.id].active_shelf = loadedWin.active_shelf;
if (loadedWin.active_group) b.windows[win.id].active_group = loadedWin.active_group;
if (Object.keys(loadedWin.groups).length > 0) b.windows[win.id].groups = Object.assign({}, loadedWin.groups);
if (Object.keys(loadedWin.folders).length > 0) b.windows[win.id].folders = Object.assign({}, loadedWin.folders);
break;
}
}
}
}
for (let win of w) {
for (let tab of win.tabs) {
VivaldiLegacyHashURL(tab);
if (tab.active) b.windows[win.id].activeTabId = tab.id;
}
}
if (opt.skip_load == false && LoadedTabs.length > 0) {
for (let win of w) {
for (tab of win.tabs) {
for (let loadedTab of LoadedTabs) {
if (loadedTab.hash == b.tabs[tab.id].hash && refTabs[loadedTab.id] == undefined) {
refTabs[loadedTab.id] = tab.id;
if (loadedTab.parent) b.tabs[tab.id].parent = loadedTab.parent;
if (loadedTab.index) b.tabs[tab.id].index = loadedTab.index;
if (loadedTab.expand) b.tabs[tab.id].expand = loadedTab.expand;
tabs_matched++;
break;
}
}
}
}
for (let tabId in b.tabs) {
if (refTabs[b.tabs[tabId].parent] != undefined) b.tabs[tabId].parent = refTabs[b.tabs[tabId].parent];
}
for (let windowId in b.windows) {
for (let group in b.windows[windowId].groups) {
if (refTabs[b.windows[windowId].groups[group].active_tab]) b.windows[windowId].groups[group].active_tab = refTabs[b.windows[windowId].groups[group].active_tab];
if (refTabs[b.windows[windowId].groups[group].prev_active_tab]) b.windows[windowId].groups[group].prev_active_tab = refTabs[b.windows[windowId].groups[group].prev_active_tab];
}
}
}
for (let win of w) {
if (b.windows[win.id]) b.windows[win.id].ttid = JSON.parse(win.extData).ext_id;
for (let tab of win.tabs) {
if (b.tabs[tab.id]) b.tabs[tab.id].ttid = JSON.parse(tab.extData).ext_id;
}
}
let Windows = {};
let Tabs = {};
for (let win of w) {
if (b.windows[win.id] != undefined && b.windows[win.id].ttid != undefined && b.windows[win.id].group_bar != undefined && b.windows[win.id].search_filter != undefined && b.windows[win.id].active_shelf != undefined && b.windows[win.id].active_group != undefined && b.windows[win.id].groups != undefined && b.windows[win.id].folders != undefined) {
Windows[b.windows[win.id].ttid] = { ttid: b.windows[win.id].ttid, group_bar: b.windows[win.id].group_bar, search_filter: b.windows[win.id].search_filter, active_shelf: b.windows[win.id].active_shelf, active_group: b.windows[win.id].active_group, groups: b.windows[win.id].groups, folders: b.windows[win.id].folders };
for (let groupId in b.windows[win.id].groups) {
if (b.tabs[b.windows[win.id].groups[groupId].active_tab]) Windows[b.windows[win.id].ttid].groups[groupId].active_tab = b.tabs[b.windows[win.id].groups[groupId].active_tab].ttid;
if (b.tabs[b.windows[win.id].groups[groupId].prev_active_tab]) Windows[b.windows[win.id].ttid].groups[groupId].prev_active_tab = b.tabs[b.windows[win.id].groups[groupId].prev_active_tab].ttid;
}
}
for (let tab of win.tabs) {
if (b.tabs[tab.id] != undefined && b.tabs[tab.id].ttid != undefined && b.tabs[tab.id].parent != undefined && b.tabs[tab.id].index != undefined && b.tabs[tab.id].expand != undefined) {
Tabs[b.tabs[tab.id].ttid] = { ttid: b.tabs[tab.id].ttid, parent: (b.tabs[b.tabs[tab.id].parent] ? b.tabs[b.tabs[tab.id].parent].ttid : b.tabs[tab.id].parent), index: b.tabs[tab.id].index, expand: b.tabs[tab.id].expand };
}
}
}
chrome.storage.local.set({ data_version: 2, windows: Windows, tabs: Tabs });
chrome.storage.local.remove("t_count");
chrome.storage.local.remove("w_count");
chrome.runtime.sendMessage({command: "reload_sidebar"});
window.location.reload();
}
if (storage.data_version == undefined || storage.data_version == 2) {
// load tabs and windows from storage
let refTabs = {};
let tabs_matched = 0;
let LoadedWindows = storage.windows ? storage.windows : {};
let LoadedTabs = storage.tabs ? storage.tabs : {};
// load debug log
if (opt.debug == true) {
if (storage.debug_log != undefined) b.debug = storage.debug_log;
}
// add data
for (let win of w) {
VivaldiAddWindowData(win);
for (let tab of win.tabs) {
VivaldiAddTabData(tab);
}
}
// if not skipping loading data
if (opt.skip_load == false) {
for (let win of w) {
if (LoadedWindows[b.windows[win.id].ttid] != undefined) {
b.windows[win.id] = Object.assign({}, LoadedWindows[b.windows[win.id].ttid]);
}
for (let tab of win.tabs) {
if (LoadedTabs[b.tabs[tab.id].ttid] != undefined) {
b.tabs[tab.id] = Object.assign({}, LoadedTabs[b.tabs[tab.id].ttid]);
refTabs[b.tabs[tab.id].ttid] = tab.id;
tabs_matched++;
} else {
if (LoadedTabs["_"+tab.index+"_"+b.windows[win.id].ttid] != undefined) {
b.tabs[tab.id] = Object.assign({}, LoadedTabs["_"+tab.index+"_"+b.windows[win.id].ttid]);
refTabs["_"+tab.index+"_"+b.windows[win.id].ttid] = tab.id;
tabs_matched++;
}
}
if (tab.active) b.windows[tab.windowId].activeTabId = tab.id;
}
}
// replace ttids to browser tabIds for parents
for (let tabId in b.tabs) {
if (refTabs[b.tabs[tabId].parent] != undefined) {
b.tabs[tabId].parent = refTabs[b.tabs[tabId].parent];
}
}
// replace ttids to browser tabIds, but of active tabs in groups
for (let winId in b.windows) {
for (let group in b.windows[winId].groups) {
if (refTabs[b.windows[winId].groups[group].active_tab] != undefined) {
b.windows[winId].groups[group].active_tab = refTabs[b.windows[winId].groups[group].active_tab];
}
if (refTabs[b.windows[winId].groups[group].prev_active_tab] != undefined) {
b.windows[winId].groups[group].prev_active_tab = refTabs[b.windows[winId].groups[group].prev_active_tab];
}
}
}
if (tabs_matched < LoadedTabs.length*0.5) {
b.safe_mode = true;
SafeModeCheck();
if (opt.debug) pushlog("started in safe mode");
if (storage.recovered_BAK) {
chrome.storage.local.set({ tabs: storage["tabs_BAK"+storage.recovered_BAK] });
chrome.storage.local.set({ windows: storage["windows_BAK"+storage.recovered_BAK] });
if (storage.recovered_BAK == 3) {
chrome.storage.local.remove("recovered_BAK");
} else {
chrome.storage.local.set({ recovered_BAK: (storage.recovered_BAK+1) });
}
} else {
chrome.storage.local.set({ recovered_BAK: 1 });
}
} else {
chrome.storage.local.remove("recovered_BAK");
}
if (opt.debug) pushlog("VivaldiStart, Current windows count is: " + w.length + "Saved windows count is: " + LoadedWindows.length + "Loaded tabs count is: " + LoadedTabs.length + "Matching tabs: " + tabs_matched);
}
}
b.bg_running = true;
VivaldiAutoSaveData(0, 1000);
VivaldiAutoSaveData(1, 300000);
VivaldiAutoSaveData(2, 600000);
VivaldiAutoSaveData(3, 1800000);
VivaldiStartListeners();
delete DefaultToolbar;
delete DefaultTheme;
delete DefaultPreferences;
delete DefaultMenu;
chrome.runtime.sendMessage({ command: "bg_started" });
});
});
}
async function VivaldiAutoSaveData(BAK, LoopTimer) {
setInterval(function() {
if (b.schedule_save > 1 || BAK > 0) {
b.schedule_save = 1;
}
if (b.bg_running && b.schedule_save > 0 && Object.keys(b.tabs).length > 1) {
chrome.windows.getAll({ windowTypes: ['normal'], populate: true }, function(w) {
let Windows = {};
let Tabs = {};
for (let win of w) {
if (b.windows[win.id] != undefined) {
if (b.windows[win.id].ttid != undefined && b.windows[win.id].group_bar != undefined && b.windows[win.id].search_filter != undefined && b.windows[win.id].active_shelf != undefined && b.windows[win.id].active_group != undefined && b.windows[win.id].groups != undefined && b.windows[win.id].folders != undefined) {
Windows[b.windows[win.id].ttid] = { ttid: b.windows[win.id].ttid, group_bar: b.windows[win.id].group_bar, search_filter: b.windows[win.id].search_filter, active_shelf: b.windows[win.id].active_shelf, active_group: b.windows[win.id].active_group, groups: b.windows[win.id].groups, folders: b.windows[win.id].folders };
for (let groupId in b.windows[win.id].groups) {
if (b.tabs[b.windows[win.id].groups[groupId].active_tab]) Windows[b.windows[win.id].ttid].groups[groupId].active_tab = b.tabs[b.windows[win.id].groups[groupId].active_tab].ttid;
if (b.tabs[b.windows[win.id].groups[groupId].prev_active_tab]) Windows[b.windows[win.id].ttid].groups[groupId].prev_active_tab = b.tabs[b.windows[win.id].groups[groupId].prev_active_tab].ttid;
}
}
} else {
VivaldiAddWindowData(win);
b.schedule_save++;
}
for (let tab of win.tabs) {
if (b.tabs[tab.id] != undefined) {
if (b.tabs[tab.id].ttid != undefined && b.tabs[tab.id].parent != undefined && b.tabs[tab.id].index != undefined && b.tabs[tab.id].expand != undefined) {
Tabs[b.tabs[tab.id].ttid] = { ttid: b.tabs[tab.id].ttid, parent: (b.tabs[b.tabs[tab.id].parent] ? b.tabs[b.tabs[tab.id].parent].ttid : b.tabs[tab.id].parent), index: b.tabs[tab.id].index, expand: b.tabs[tab.id].expand };
}
} else {
VivaldiAddTabData(tab);
}
}
}
chrome.storage.local.set((BAK == 0 ? { windows: Windows, tabs: Tabs } : (BAK == 1 ? { windows_BAK1: Windows, tabs_BAK1: Tabs } : (BAK == 2 ? { windows_BAK2: Windows, tabs_BAK2: Tabs } : { windows_BAK3: Windows, tabs_BAK3: Tabs }))));
b.schedule_save--;
});
}
if (opt.debug == true) chrome.storage.local.set({ debug_log: b.debug });
}, LoopTimer);
}
function VivaldiAddWindowData(win) {
let extData = JSON.parse(win.extData);
if (b.windows[win.id] == undefined) b.windows[win.id] = { ttid: (win.extData.match("ext_id") != null ? JSON.parse(win.extData).ext_id : win.index), activeTabId: 0, group_bar: opt.groups_toolbar_default, search_filter: "url", active_shelf: "", active_group: "tab_list", groups: { tab_list: { id: "tab_list", index: 0, active_tab: 0, prev_active_tab: 0, name: labels.ungrouped_group, font: "" } }, folders: {} };
return b.windows[win.id].ttid;
}
function VivaldiAddTabData(tab) {
if (b.tabs[tab.id] == undefined) {
b.tabs[tab.id] = { ttid: "_", parent: tab.pinned ? "pin_list" : (b.windows[tab.windowId] ? b.windows[tab.windowId].active_group : "tab_list"), index: (Object.keys(b.tabs).length + 1), expand: "n" };
}
if (tab.extData.match("ext_id") != null) {
b.tabs[tab.id].ttid = JSON.parse(tab.extData).ext_id;
b.schedule_save++;
} else {
b.tabs[tab.id].ttid = "_"+tab.index+"_"+b.windows[tab.windowId].ttid;
b.schedule_save++;
}
return b.tabs[tab.id].ttid;
}
function VivaldiStartListeners() { // start all listeners
chrome.tabs.onCreated.addListener(function(tab) {
// VivaldiAddWindowData(tab.windowId);
// let extData = tab.extData.match("ext_id") != null ? JSON.parse(tab.extData).ext_id : false;
// if (extData) {
// for (let tabId in b.tabs) {
// if (extData === b.tabs[tabId].ttid) {
// b.tabs[tab.id] = b.tabs[tabId];
// delete b.tabs[tabId];
// break;
// }
// }
// }
let prevActiveTabId = b.windows[tab.windowId].activeTabId;
VivaldiAddTabData(tab);
OnMessageTabCreated(tab, prevActiveTabId);
});
chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) {
let SiblingTabs = b.tabs[tabId] ? GetChildren(b.tabs, b.tabs[tabId].parent) : [];
let SiblingFolders = b.tabs[tabId] ? GetChildren(b.windows[removeInfo.windowId].folders, b.tabs[tabId].parent) : [];
UnshiftChildrenIndexes(SiblingTabs, b.tabs[tabId].index, SiblingFolders, removeInfo.windowId);
if (b.EmptyTabs.indexOf(tabId) != -1) {
b.EmptyTabs.splice(b.EmptyTabs.indexOf(tabId), 1);
}
setTimeout(function() { chrome.runtime.sendMessage({ command: "tab_removed", windowId: removeInfo.windowId, tabId: tabId }); }, 5);
delete b.tabs[tabId];
b.schedule_save++;
});
chrome.tabs.onAttached.addListener(function(tabId, attachInfo) {
chrome.tabs.get(tabId, function(tab) {
chrome.runtime.sendMessage({ command: "tab_attached", windowId: attachInfo.newWindowId, tab: tab, tabId: tabId, ParentId: b.tabs[tabId].parent });
});
b.schedule_save++;
});
chrome.tabs.onDetached.addListener(function(tabId, detachInfo) {
chrome.runtime.sendMessage({ command: "tab_detached", windowId: detachInfo.oldWindowId, tabId: tabId });
b.schedule_save++;
});
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (changeInfo.pinned != undefined) {
if (changeInfo.pinned == true) {
b.tabs[tabId].parent = "pin_list";
}
if (changeInfo.pinned == false) {
b.tabs[tabId].parent = "tab_list";
}
b.schedule_save++;
}
if (changeInfo.url != undefined) { // if set to append when url changes and matches pre-set group
if (tab.pinned == false) {
if (opt.move_tabs_on_url_change == "always" || ((opt.move_tabs_on_url_change == "from_empty" || opt.move_tabs_on_url_change == "from_empty_b") && b.EmptyTabs.indexOf(tabId) != -1)) {
AppendTabToGroupOnRegexMatch(tabId, tab.windowId, changeInfo.url);
}
}
if (changeInfo.url != b.newTabUrl && b.EmptyTabs.indexOf(tabId) != -1) {
b.EmptyTabs.splice(b.EmptyTabs.indexOf(tabId), 1);
}
}
if (changeInfo.title != undefined && !tab.active) {
chrome.runtime.sendMessage({ command: "tab_attention", windowId: tab.windowId, tabId: tabId });
}
chrome.runtime.sendMessage({ command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tabId, changeInfo: changeInfo });
});
chrome.tabs.onMoved.addListener(function(tabId, moveInfo) {
b.schedule_save++;
});
chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId) {
chrome.tabs.get(addedTabId, function(tab) {
if (addedTabId == removedTabId) {
chrome.runtime.sendMessage({ command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tab.id, changeInfo: { status: tab.status, url: tab.url, title: tab.title, audible: tab.audible, mutedInfo: tab.mutedInfo } });
} else {
ReplaceParents(tabId, tab.id);
if (b.tabs[removedTabId]) {
b.tabs[addedTabId] = b.tabs[removedTabId];
} else {
VivaldiAddTabData(tab);
}
chrome.runtime.sendMessage({ command: "tab_removed", windowId: tab.windowId, tabId: removedTabId });
chrome.runtime.sendMessage({ command: "tab_attached", windowId: tab.windowId, tab: tab, tabId: addedTabId });
delete b.tabs[removedTabId];
}
b.schedule_save++;
});
});
chrome.tabs.onActivated.addListener(function(activeInfo) {
if (b.windows[activeInfo.windowId]) {
b.windows[activeInfo.windowId].activeTabId = activeInfo.tabId;
}
chrome.runtime.sendMessage({ command: "tab_activated", windowId: activeInfo.windowId, tabId: activeInfo.tabId });
setTimeout(function() {chrome.tabs.query({windowId: activeInfo.windowId}, function(tabs) {for (let tab of tabs) {if ((b.tabs[tab.id].ttid).startsWith("_") || tab.id === activeInfo.tabId) VivaldiAddTabData(tab);}});}, 500);
b.schedule_save++;
});
chrome.windows.onCreated.addListener(function(window) {
VivaldiAddWindowData(window);
b.schedule_save++;
});
chrome.windows.onRemoved.addListener(function(windowId) {
delete b.windows[windowId];
b.schedule_save++;
});
chrome.runtime.onSuspend.addListener(function() {
b.bg_running = false;
});
}

92
global.js Normal file
View File

@ -0,0 +1,92 @@
// GLOBAL VARIABLES
let browserId = navigator.userAgent.match("Opera|OPR") !== null ? "O" : (navigator.userAgent.match("Vivaldi") !== null ? "V" : (navigator.userAgent.match("Firefox") !== null ? "F" : "C"))
let opt = {};
let labels = {
clear_filter: chrome.i18n.getMessage("caption_clear_filter"),
loading: chrome.i18n.getMessage("caption_loading"),
searchbox: chrome.i18n.getMessage("caption_searchbox"),
ungrouped_group: chrome.i18n.getMessage("caption_ungrouped_group"),
noname_group: chrome.i18n.getMessage("caption_noname_group")
};
// DEFAULTS NEEDED FOR START AND FOR OPTIONS PAGE
const DefaultToolbar = {
toolbar_main: ["button_new", "button_pin", "button_undo", "button_search", "button_tools", "button_groups", "button_backup", "button_folders"],
toolbar_search: ["button_filter_type", "filter_search_go_prev", "filter_search_go_next"],
toolbar_shelf_tools: (browserId == "F" ? ["button_manager_window", "button_options", "button_unload", "button_detach", "button_reboot"] : ["button_manager_window", "button_options", "button_bookmarks", "button_downloads", "button_history", "button_settings", "button_extensions", "button_unload", "button_detach", "button_reboot"]),
toolbar_shelf_groups: ["button_groups_toolbar_hide", "button_new_group", "button_remove_group", "button_edit_group", "button_import_group", "button_export_group"],
toolbar_shelf_backup: (browserId == "F" ? ["button_import_bak", "button_import_merge_bak", "button_export_bak"] : ["button_import_bak", "button_import_merge_bak", "button_export_bak", "button_load_bak1", "button_load_bak2", "button_load_bak3"]),
toolbar_shelf_folders: ["button_new_folder", "button_remove_folder", "button_edit_folder"]
};
const DefaultMenu = {
all_entries: [["s_pin","menu_new_pin"],["s_newt","menu_new_tab"],["s_unpt","menu_unpin_tab"],["s_pit","menu_pin_tab"],["s_newf","menu_new_folder"],["s_renf","menu_rename_folder"],["s_delf","menu_delete_folder"],["s_dupt","menu_duplicate_tab"],["s_undclo","menu_undo_close_tab"],["s_bkt","menu_bookmark_tree"],["s_expat","menu_expand_tree"],["s_collt","menu_collapse_tree"],["s_expaa","menu_expand_all"],["s_colla","menu_collapse_all"],["s_deta","menu_detach_tab"],["s_rel","menu_reload_tab"],["s_unlo","menu_unload"],["s_unlt","menu_unload_tree"],["s_clo","menu_close"],["s_clot","menu_close_tree"],["s_cloo","menu_close_other"],["s_mut","menu_mute_tab"],["s_mutt","menu_mute_tree"],["s_unmu","menu_unmute_tab"],["s_unmut","menu_unmute_tree"],["s_mutot","menu_mute_other"],["s_unmutot","menu_unmute_other"],["s_newg","menu_new_group"],["s_reng","menu_rename_group"],["s_delg","menu_delete_group"],["s_delgclo","menu_delete_group_tabs_close"],["s_gunlo","menu_groups_unload"],["s_ghiber","menu_groups_hibernate"],["s_gtbcl","menu_group_tabs_close"],["s_gbk","menu_bookmark_group"],["s_mngr_wnd","menu_manager_window"],["s_tts","menu_treetabs_settings"]],
pin: [[ false,true ],[ false,false ],[ true,true ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ true,true ],[ true,true ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ true,true ],[ false,true ],[ false,false ],[ false,false ],[ true,false ],[ false,false ],[ false,true ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ true,true ],[ false,true ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,true ],[ true,true ]],
tab: [[ false,false ],[ false,true ],[ true,false ],[ false,true ],[ true,true ],[ false, false ],[ false,false ],[ true,true ],[ true,true ],[ false,true ],[ false,false ],[ false,false ],[ true,true ],[ false,true ],[ true,true ],[ false,true ],[ false,false ],[ false,false ],[ true,true ],[ false,false ],[ false,true ],[ false,false ],[ false, false ],[ false,false ],[ false,false ],[ true,true ],[ false,true ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,true ],[ true,true ]],
folder: [[ false,false ],[ false,true ],[ false,false ],[ false,false ],[ false,true ],[ true,true ],[ false,true ],[ false,false ],[ false,false ],[ true,true ],[ false,false ],[ false,false ],[ true,true ],[ false,true ],[ true,true ],[ false,false ],[ true,true ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,true ],[ false,false ],[ false,true ],[ false,false ],[ false,false ],[ false,false ],[ false,true ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,true ],[ true,true ]],
global: [[ false,true ],[ false,true ],[ false,false ],[ false,false ],[ false,true ],[ false,false ],[ false,false ],[ false,false ],[ true,true ],[ false,false ],[ false,false ],[ false,false ],[ true,true ],[ false,true ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ true,true ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ true,true ],[ false,true ],[ true,true ]],
group: [[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,true ],[ false,true ],[ false,true ],[ false,true ],[ true,true ],[ false,true ],[ true,true ],[ true,true ],[ false,true ],[ true,true ]]
// name: [[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ],[ false,false ]]
};
const DefaultTheme = {
ToolbarShow: true,
ColorsSet: {},
TabsSizeSetNumber: 2,
TabsMargins: "2",
theme_name: "untitled",
theme_version: 4
};
const DefaultPreferences = {
hide_other_groups_tabs_firefox: false,
show_toolbar: true,
skip_load: false,
pin_attention_blinking: true,
audio_blinking: true,
pin_list_multi_row: true,
append_pinned_tab: "last",
always_show_close: false,
never_show_close: false,
allow_pin_close: false,
append_child_tab: "bottom",
append_child_tab_after_limit: "after",
append_orphan_tab: "bottom",
after_closing_active_tab: "below_seek_in_parent",
append_tab_from_toolbar: "group_root",
collapse_other_trees: false,
open_tree_on_hover: true,
promote_children: true,
promote_children_in_first_child: true,
max_tree_depth: -1,
max_tree_drag_drop: true,
switch_with_scroll: false,
syncro_tabbar_tabs_order: true,
show_counter_groups: true,
show_counter_tabs: true,
show_counter_tabs_hints: true,
groups_toolbar_default: true,
syncro_tabbar_groups_tabs_order: true,
midclick_tab: "close_tab",
dbclick_tab: "new_tab",
dbclick_group: "new_tab",
// dbclick_group_bar: "new_group",
midclick_group: "nothing",
midclick_folder: "nothing",
dbclick_folder: "rename_folder",
debug: false,
orphaned_tabs_to_ungrouped: false,
tab_group_regexes: [],
move_tabs_on_url_change: "never",
autosave_max_to_keep: 5,
autosave_interval: 15
};
// GLOBAL FUNCTIONS
function GenerateRandomID() {
let letters = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "K", "L", "M", "N", "O", "P", "R", "S", "T", "Q", "U", "V", "W", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "k", "l", "m", "n", "o", "p", "r", "s", "t", "q", "u", "v", "w", "y", "z"];
let random = "";
for (let letter = 0; letter < 14; letter++) { random += letters[Math.floor(Math.random() * letters.length)]; }
return random;
}

View File

@ -1,716 +0,0 @@
// 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/
function StartBackgroundListeners() {
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if (message.command == "reload") {
window.location.reload();
return;
}
if (message.command == "reload_options") {
opt = Object.assign({}, message.opt);
return;
}
if (message.command == "get_windows") {
sendResponse(b.windows);
return;
}
if (message.command == "get_folders") {
if (b.windows[message.windowId]) {
sendResponse(b.windows[message.windowId].folders);
}
return;
}
if (message.command == "save_folders") {
if (b.windows[message.windowId]) {
b.windows[message.windowId].folders = Object.assign({}, message.folders);
b.schedule_save++;
}
return;
}
if (message.command == "get_groups") {
if (b.windows[message.windowId]) {
sendResponse(b.windows[message.windowId].groups);
}
return;
}
if (message.command == "save_groups" && browserId == "F") {
if (b.windows[message.windowId]) {
b.windows[message.windowId].groups = Object.assign({}, message.groups);
for (let group in b.windows[message.windowId].groups) {
if (b.tabs[b.windows[message.windowId].groups[group].active_tab]) {
b.windows[message.windowId].groups[group].active_tab_ttid = b.tabs[b.windows[message.windowId].groups[group].active_tab].ttid;
}
if (b.tabs[b.windows[message.windowId].groups[group].prev_active_tab]) {
b.windows[message.windowId].groups[group].prev_active_tab_ttid = b.tabs[b.windows[message.windowId].groups[group].prev_active_tab].ttid;
}
}
b.schedule_save++;
}
return;
}
if (message.command == "save_groups" && browserId != "F") {
if (b.windows[message.windowId]) {
b.windows[message.windowId].groups = Object.assign({}, message.groups);
b.schedule_save++;
}
return;
}
if (message.command == "set_active_group") {
if (b.windows[message.windowId]) {
b.windows[message.windowId].active_group = message.active_group;
b.schedule_save++;
}
return;
}
if (message.command == "get_active_group") {
if (b.windows[message.windowId]) {
sendResponse(b.windows[message.windowId].active_group);
}
return;
}
if (message.command == "set_search_filter") {
if (b.windows[message.windowId]) {
b.windows[message.windowId].search_filter = message.search_filter;
b.schedule_save++;
}
return;
}
if (message.command == "get_search_filter") {
if (b.windows[message.windowId]) {
sendResponse(b.windows[message.windowId].search_filter);
}
return;
}
if (message.command == "set_active_shelf") {
if (b.windows[message.windowId]) {
b.windows[message.windowId].active_shelf = message.active_shelf;
b.schedule_save++;
}
return;
}
if (message.command == "get_active_shelf") {
if (b.windows[message.windowId]) {
sendResponse(b.windows[message.windowId].active_shelf);
}
return;
}
if (message.command == "set_group_bar") {
if (b.windows[message.windowId]) {
b.windows[message.windowId].group_bar = message.group_bar;
b.schedule_save++;
}
return;
}
if (message.command == "get_group_bar") {
if (b.windows[message.windowId]) {
sendResponse(b.windows[message.windowId].group_bar);
}
return;
}
if (message.command == "get_browser_tabs") {
sendResponse(b.tabs);
return;
}
if (message.command == "is_bg_ready") {
sendResponse(b.running);
return;
}
if (message.command == "update_tab" && browserId == "F") {
if (b.tabs[message.tabId]) {
if (message.tab.index) {
b.tabs[message.tabId].index = message.tab.index;
}
if (message.tab.expand) {
b.tabs[message.tabId].expand = message.tab.expand;
}
if (message.tab.parent) {
b.tabs[message.tabId].parent = message.tab.parent;
if (b.tabs[message.tab.parent]) {
b.tabs[message.tabId].parent_ttid = b.tabs[message.tab.parent].ttid;
} else {
b.tabs[message.tabId].parent_ttid = "";
}
}
b.schedule_save++;
} else {
b.tabs[tabId] = {ttid: "", parent: message.tab.parent, parent_ttid: "", index: message.tab.index, expand: message.tab.expand};
b.schedule_save++;
}
return;
}
if (message.command == "update_tab" && browserId != "F") {
if (b.tabs[message.tabId]) {
if (message.tab.index) {
b.tabs[message.tabId].index = message.tab.index;
}
if (message.tab.expand) {
b.tabs[message.tabId].expand = message.tab.expand;
}
if (message.tab.parent) {
b.tabs[message.tabId].parent = message.tab.parent;
}
b.schedule_save++;
} else {
b.tabs[tabId] = {hash: 0, parent: message.tab.parent, index: message.tab.index, expand: message.tab.expand};
b.schedule_save++;
}
return;
}
if (message.command == "update_all_tabs" && browserId == "F") {
for (let i = 0; i < message.pins.length; i++) {
if (b.tabs[message.pins[i].id]) {
b.tabs[message.pins[i].id].parent = "pin_list";
b.tabs[message.pins[i].id].parent_ttid = "";
b.tabs[message.pins[i].id].expand = "";
b.tabs[message.pins[i].id].index = message.pins[i].index;
}
}
for (let j = 0; j < message.tabs.length; j++) {
if (b.tabs[message.tabs[j].id]) {
b.tabs[message.tabs[j].id].parent = message.tabs[j].parent;
b.tabs[message.tabs[j].id].expand = message.tabs[j].expand;
b.tabs[message.tabs[j].id].index = message.tabs[j].index;
if (b.tabs[message.tabs[j].parent]) {
b.tabs[message.tabs[j].id].parent_ttid = b.tabs[message.tabs[j].parent].ttid;
} else {
b.tabs[message.tabs[j].id].parent_ttid = "";
}
}
}
b.schedule_save++;
return;
}
if (message.command == "update_all_tabs" && browserId != "F") {
for (let i = 0; i < message.pins.length; i++) {
if (b.tabs[message.pins[i].id]) {
b.tabs[message.pins[i].id].parent = "pin_list";
b.tabs[message.pins[i].id].expand = "";
b.tabs[message.pins[i].id].index = message.pins[i].index;
}
}
for (let j = 0; j < message.tabs.length; j++) {
if (b.tabs[message.tabs[j].id]) {
b.tabs[message.tabs[j].id].parent = message.tabs[j].parent;
b.tabs[message.tabs[j].id].expand = message.tabs[j].expand;
b.tabs[message.tabs[j].id].index = message.tabs[j].index;
}
}
b.schedule_save++;
return;
}
if (message.command == "discard_tab") {
DiscardTab(message.tabId);
return;
}
if (message.command == "discard_window") {
DiscardWindow(message.windowId);
return;
}
if (message.command == "remove_tab_from_empty_tabs") {
setTimeout(function() {
if (b.EmptyTabs.indexOf(message.tabId) != -1) {
b.EmptyTabs.splice(b.EmptyTabs.indexOf(message.tabId), 1);
}
}, 100);
return;
}
if (message.command == "debug") {
pushlog(message.log);
return;
}
});
}
function QuantumStartListeners() {
browser.browserAction.onClicked.addListener(function() {
browser.sidebarAction.setPanel({panel: (browser.extension.getURL("/sidebar.html")) });
browser.sidebarAction.open();
});
chrome.tabs.onCreated.addListener(function(tab) {
let prevActiveTabId = b.windows[tab.windowId].activeTabId;
b.NewTabsQueue.push(tab.id);
let t = Promise.resolve(browser.sessions.getTabValue(tab.id, "TTdata")).then(function(TabData) {
if (TabData != undefined) {
b.tabs[tab.id] = Object.assign({}, TabData);
let originalParent = TabData.parent_ttid == "" ? undefined : (b.tt_ids[TabData.parent_ttid] ? b.tt_ids[TabData.parent_ttid] : TabData.parent_ttid);
chrome.runtime.sendMessage({command: "tab_created", windowId: tab.windowId, tabId: tab.id, tab: tab, ParentId: originalParent, InsertAfterId: undefined, Append: undefined});
} else {
QuantumAppendTabTTId(tab);
OnMessageTabCreated(tab.id, prevActiveTabId);
}
});
});
chrome.tabs.onAttached.addListener(function(tabId, attachInfo) {
let oldId = tabId;
chrome.tabs.get(oldId, function(tab) {
ReplaceParents(oldId, tab.id);
chrome.runtime.sendMessage({command: "tab_attached", windowId: attachInfo.newWindowId, tab: tab, tabId: tab.id, ParentId: b.tabs[tab.id].parent});
b.schedule_save++;
});
});
chrome.tabs.onDetached.addListener(function(tabId, detachInfo) {
chrome.runtime.sendMessage({command: "tab_detached", windowId: detachInfo.oldWindowId, tabId: tabId});
});
chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) {
if (b.EmptyTabs.indexOf(tabId) != -1) {
b.EmptyTabs.splice(b.EmptyTabs.indexOf(tabId), 1);
}
setTimeout(function() {
chrome.runtime.sendMessage({command: "tab_removed", windowId: removeInfo.windowId, tabId: tabId});
}, 5);
// setTimeout(function() {
// delete b.tabs[tabId];
// },60000);
b.schedule_save++;
});
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (changeInfo.pinned == true) {
if (b.tabs[tabId]) {
b.tabs[tabId].parent = "pin_list";
b.tabs[tabId].parent_ttid = "";
b.schedule_save++;
}
}
if (changeInfo.pinned == false) {
if (b.tabs[tabId]) {
b.tabs[tabId].parent = "tab_list";
b.tabs[tabId].parent_ttid = "";
b.schedule_save++;
}
}
if (changeInfo.url != undefined) { // if set to append when url changes and matches pre-set group
if (opt.move_tabs_on_url_change == "always" || ((opt.move_tabs_on_url_change == "from_empty" || opt.move_tabs_on_url_change == "from_empty_b") && b.EmptyTabs.indexOf(tabId) != -1)) {
AppendTabToGroupOnRegexMatch(tabId, tab.windowId, changeInfo.url);
}
if (changeInfo.url != b.newTabUrl && b.EmptyTabs.indexOf(tabId) != -1) {
b.EmptyTabs.splice(b.EmptyTabs.indexOf(tabId), 1);
}
}
if (changeInfo.title != undefined && !tab.active) {
chrome.runtime.sendMessage({command: "tab_attention", windowId: tab.windowId, tabId: tabId});
}
chrome.runtime.sendMessage({command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tabId, changeInfo: changeInfo});
});
chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId) {
chrome.tabs.get(addedTabId, function(tab) {
if (addedTabId == removedTabId) {
chrome.runtime.sendMessage({command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tab.id, changeInfo: {status: tab.status, url: tab.url, title: tab.title, audible: tab.audible, mutedInfo: tab.mutedInfo}});
} else {
if (b.tabs[removedTabId]) {
b.tabs[addedTabId] = b.tabs[removedTabId];
}
ReplaceParents(tabId, tab.id);
chrome.runtime.sendMessage({command: "tab_removed", windowId: tab.windowId, tabId: removedTabId});
chrome.runtime.sendMessage({command: "tab_attached", windowId: tab.windowId, tab: tab, tabId: addedTabId, ParentId: b.tabs[addedTabId].parent});
// delete ttid[b.tabs[removedTabId].ttid];
// delete b.tabs[removedTabId];
}
setTimeout(function() {
QuantumAppendTabTTId(tab);
b.schedule_save++;
}, 100);
});
});
chrome.tabs.onActivated.addListener(function(activeInfo) {
if (b.windows[activeInfo.windowId]) {
b.windows[activeInfo.windowId].activeTabId = activeInfo.tabId;
}
chrome.runtime.sendMessage({command: "tab_activated", windowId: activeInfo.windowId, tabId: activeInfo.tabId});
b.schedule_save++;
});
chrome.windows.onCreated.addListener(function(window) {
let win = Promise.resolve(browser.sessions.getWindowValue(window.id, "TTdata")).then(function(WindowData) {
if (WindowData != undefined) {
b.windows[window.id] = Object.assign({}, WindowData);
} else {
QuantumAppendWinTTId(window.id);
}
b.schedule_save++;
});
});
chrome.windows.onRemoved.addListener(function(windowId) {
// delete b.windows[windowId];
b.schedule_save++;
});
// chrome.sessions.onChanged.addListener(function(session) {
// chrome.windows.getAll({windowTypes: ['normal'], populate: false}, function(w) {
// chrome.tabs.query({}, function(t) {
// for (let wiInd = 0; wiInd < w.length; wiInd++) {
// if (b.windows[w[wiInd].id] == undefined) {
// chrome.runtime.sendMessage({command: "reload_sidebar"});
// window.location.reload();
// }
// }
// for (let tbInd = 0; tbInd < t.length; tbInd++) {
// if (b.tabs[t[tbInd].id] == undefined) {
// chrome.runtime.sendMessage({command: "reload_sidebar"});
// window.location.reload();
// }
// }
// });
// });
// });
}
function ChromiumStartListeners() { // start all listeners
chrome.tabs.onCreated.addListener(function(tab) {
b.NewTabsQueue.push(tab.id);
ChromiumHashURL(tab);
OnMessageTabCreated(tab.id, b.windows[tab.windowId].activeTabId);
});
chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) {
if (b.EmptyTabs.indexOf(tabId) != -1) {
b.EmptyTabs.splice(b.EmptyTabs.indexOf(tabId), 1);
}
setTimeout(function() { chrome.runtime.sendMessage({command: "tab_removed", windowId: removeInfo.windowId, tabId: tabId}); },5);
delete b.tabs[tabId];
b.schedule_save++;
});
chrome.tabs.onAttached.addListener(function(tabId, attachInfo) {
chrome.tabs.get(tabId, function(tab) {
chrome.runtime.sendMessage({command: "tab_attached", windowId: attachInfo.newWindowId, tab: tab, tabId: tabId, ParentId: b.tabs[tabId].parent});
});
b.schedule_save++;
});
chrome.tabs.onDetached.addListener(function(tabId, detachInfo) {
chrome.runtime.sendMessage({command: "tab_detached", windowId: detachInfo.oldWindowId, tabId: tabId});
b.schedule_save++;
});
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (b.tabs[tabId] == undefined || changeInfo.url != undefined) {
ChromiumHashURL(tab);
}
if (changeInfo.pinned != undefined) {
if (changeInfo.pinned == true) {
b.tabs[tabId].parent = "pin_list";
}
if (changeInfo.pinned == false) {
b.tabs[tabId].parent = "tab_list";
}
b.schedule_save++;
}
if (changeInfo.url != undefined) { // if set to append when url changes and matches pre-set group
if (opt.move_tabs_on_url_change == "always" || ((opt.move_tabs_on_url_change == "from_empty" || opt.move_tabs_on_url_change == "from_empty_b") && b.EmptyTabs.indexOf(tabId) != -1)) {
AppendTabToGroupOnRegexMatch(tabId, tab.windowId, changeInfo.url);
}
if (changeInfo.url != b.newTabUrl && b.EmptyTabs.indexOf(tabId) != -1) {
b.EmptyTabs.splice(b.EmptyTabs.indexOf(tabId), 1);
}
}
if (changeInfo.title != undefined && !tab.active) {
chrome.runtime.sendMessage({command: "tab_attention", windowId: tab.windowId, tabId: tabId});
}
chrome.runtime.sendMessage({command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tabId, changeInfo: changeInfo});
});
chrome.tabs.onMoved.addListener(function(tabId, moveInfo) {
b.schedule_save++;
});
chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId) {
chrome.tabs.get(addedTabId, function(tab) {
if (addedTabId == removedTabId) {
chrome.runtime.sendMessage({command: "tab_updated", windowId: tab.windowId, tab: tab, tabId: tab.id, changeInfo: {status: tab.status, url: tab.url, title: tab.title, audible: tab.audible, mutedInfo: tab.mutedInfo}});
} else {
ReplaceParents(tabId, tab.id);
if (b.tabs[removedTabId]) {
b.tabs[addedTabId] = b.tabs[removedTabId];
} else {
ChromiumHashURL(tab);
}
chrome.runtime.sendMessage({command: "tab_removed", windowId: tab.windowId, tabId: removedTabId});
chrome.runtime.sendMessage({command: "tab_attached", windowId: tab.windowId, tab: tab, tabId: addedTabId});
delete b.tabs[removedTabId];
}
b.schedule_save++;
});
});
chrome.tabs.onActivated.addListener(function(activeInfo) {
if (b.windows[activeInfo.windowId]) {
b.windows[activeInfo.windowId].activeTabId = activeInfo.tabId;
}
chrome.runtime.sendMessage({command: "tab_activated", windowId: activeInfo.windowId, tabId: activeInfo.tabId});
b.schedule_save++;
});
chrome.windows.onCreated.addListener(function(window) {
ChromiumAddWindowData(window.id);
// b.windows[window.id] = {group_bar: opt.groups_toolbar_default, search_filter: "url", active_shelf: "", active_group: "tab_list", groups: {tab_list: {id: "tab_list", index: 0, active_tab: 0, prev_active_tab: 0, name: labels.ungrouped_group, font: ""}}, folders: {}};
b.schedule_save++;
});
chrome.windows.onRemoved.addListener(function(windowId) {
delete b.windows[windowId];
b.schedule_save++;
});
chrome.runtime.onSuspend.addListener(function() {
b.running = false;
});
}
function OnMessageTabCreated(tabId, activeTabId) {
if (b.NewTabsQueue.length > 0 && b.NewTabsQueue[0] == tabId) {
chrome.tabs.get(tabId, function(NewTab) { // get tab again as reported tab's url is empty! Also for some reason firefox sends tab with "active == false" even if tab is active (THIS IS POSSIBLY A NEW BUG IN FF 60!)
let ParentId;
let AfterId;
let append;
if (b.windows[NewTab.windowId] && NewTab.active) {
b.windows[NewTab.windowId].groups[b.windows[NewTab.windowId].active_group].active_tab = NewTab.id;
}
if (NewTab.url == b.newTabUrl) {
b.EmptyTabs.push(tabId);
}
if (NewTab.pinned) {
let PinTabs = GetChildren("pin_list");
b.tabs[NewTab.id].parent = "pin_list";
if (browserId == "F") {
b.tabs[NewTab.id].parent_ttid = "";
}
for (let i = PinTabs.indexOf(NewTab.openerTabId)+1; i < PinTabs.length; i++) { // shift next siblings indexes
b.tabs[PinTabs[i]].index += 1;
}
b.tabs[NewTab.id].index = NewTab.index;
} else {
if (opt.append_orphan_tab == "as_child" && opt.orphaned_tabs_to_ungrouped == false) {
NewTab.openerTabId = activeTabId;
}
if (NewTab.openerTabId) { // child case
let OpenerSiblings = GetChildren(b.tabs[NewTab.openerTabId].parent);
if (opt.append_child_tab == "after") { // place tabs flat
b.tabs[NewTab.id].parent = b.tabs[NewTab.openerTabId].parent;
if (browserId == "F") {
b.tabs[NewTab.id].parent_ttid = b.tabs[NewTab.openerTabId].parent_ttid;
}
for (let i = OpenerSiblings.indexOf(NewTab.openerTabId)+1; i < OpenerSiblings.length; i++) { // shift next siblings indexes
b.tabs[OpenerSiblings[i]].index += 1;
}
b.tabs[NewTab.id].index = b.tabs[NewTab.openerTabId].index+1;
AfterId = NewTab.openerTabId;
} else {
if (opt.max_tree_depth == 0) { // place tabs flat if limit is set to 0
b.tabs[NewTab.id].parent = b.tabs[NewTab.openerTabId].parent;
if (browserId == "F"){
b.tabs[NewTab.id].parent_ttid = b.tabs[NewTab.openerTabId].parent_ttid;
}
if (opt.append_child_tab_after_limit == "after") { // max tree depth, place tab after parent
for (let i = OpenerSiblings.indexOf(NewTab.openerTabId)+1; i < OpenerSiblings.length; i++) { // shift next siblings indexes
b.tabs[OpenerSiblings[i]].index += 1;
}
b.tabs[NewTab.id].index = b.tabs[NewTab.openerTabId].index+1;
AfterId = NewTab.openerTabId;
}
if (opt.append_child_tab_after_limit == "top" && opt.append_child_tab != "after") { // max tree depth, place tab on top (above parent)
for (let i = 0; i < OpenerSiblings.length; i++) { // shift all siblings indexes
b.tabs[OpenerSiblings[i]].index += 1;
}
b.tabs[NewTab.id].index = 0;
ParentId = b.tabs[NewTab.id].parent;
}
if (opt.append_child_tab_after_limit == "bottom" && opt.append_child_tab != "after") { // max tree depth, place tab on bottom (below parent)
if (OpenerSiblings.length > 0) {
b.tabs[NewTab.id].index = b.tabs[OpenerSiblings[OpenerSiblings.length-1]].index+1;
} else {
b.tabs[NewTab.id].index = 1;
}
ParentId = b.tabs[NewTab.id].parent;
append = true;
}
} else {
let Parents = GetTabParents(NewTab.openerTabId);
let OpenerChildren = GetChildren(NewTab.openerTabId);
if (opt.max_tree_depth < 0 || (opt.max_tree_depth > 0 && Parents.length < opt.max_tree_depth)) { // append to tree on top and bottom
b.tabs[NewTab.id].parent = NewTab.openerTabId;
if (browserId == "F"){
b.tabs[NewTab.id].parent_ttid = b.tabs[NewTab.openerTabId].ttid;
}
if (opt.append_child_tab == "top") { // place child tab at the top (reverse hierarchy)
for (let i = 0; i < OpenerChildren.length; i++) { // shift all siblings indexes
b.tabs[OpenerChildren[i]].index += 1;
}
b.tabs[NewTab.id].index = 0;
ParentId = b.tabs[NewTab.id].parent;
}
if (opt.append_child_tab == "bottom") { // place child tab at the bottom
if (OpenerChildren.length > 0) {
b.tabs[NewTab.id].index = b.tabs[OpenerChildren[OpenerChildren.length-1]].index+1;
} else {
b.tabs[NewTab.id].index = 0;
}
ParentId = b.tabs[NewTab.id].parent;
append = true;
}
} else {
if (opt.max_tree_depth > 0 && Parents.length >= opt.max_tree_depth) { // if reached depth limit of the tree
b.tabs[NewTab.id].parent = b.tabs[NewTab.openerTabId].parent;
if (browserId == "F"){
b.tabs[NewTab.id].parent_ttid = b.tabs[NewTab.openerTabId].parent_ttid;
}
if (opt.append_child_tab_after_limit == "after") { // tab will append after opener
for (let i = OpenerSiblings.indexOf(NewTab.openerTabId)+1; i < OpenerSiblings.length; i++) { // shift next siblings indexes
b.tabs[OpenerSiblings[i]].index += 1;
}
b.tabs[NewTab.id].index = b.tabs[NewTab.openerTabId].index+1;
AfterId = NewTab.openerTabId;
}
if (opt.append_child_tab_after_limit == "top") { // tab will append on top
for (let i = 0; i < OpenerChildren.length; i++) { // shift all siblings indexes
b.tabs[OpenerChildren[i]].index += 1;
}
b.tabs[NewTab.id].index = 0;
ParentId = b.tabs[NewTab.id].parent;
}
if (opt.append_child_tab_after_limit == "bottom") { // tab will append on bottom
if (OpenerSiblings.length > 0) {
b.tabs[NewTab.id].index = b.tabs[OpenerSiblings[OpenerSiblings.length-1]].index+1;
} else {
b.tabs[NewTab.id].index = 1;
}
ParentId = b.tabs[NewTab.id].parent;
append = true;
}
}
}
}
}
} else { // orphan tab
if (opt.orphaned_tabs_to_ungrouped == true) { // if set to append orphan tabs to ungrouped group
let TabListTabs = GetChildren("tab_list");
b.tabs[NewTab.id].index = b.tabs[TabListTabs[TabListTabs.length-1]].index+1;
ParentId = "tab_list";
append = true;
} else {
if (opt.append_orphan_tab == "after_active") {
if (b.windows[NewTab.windowId] && b.windows[NewTab.windowId].activeTabId) {
if (b.tabs[activeTabId]) {
let ActiveSiblings = GetChildren(b.tabs[activeTabId].parent);
b.tabs[NewTab.id].parent = b.tabs[activeTabId].parent;
for (let i = ActiveSiblings.indexOf(activeTabId)+1; i < ActiveSiblings.length; i++) { // shift next siblings indexes
b.tabs[ActiveSiblings[i]].index += 1;
}
b.tabs[NewTab.id].index = b.tabs[activeTabId].index+1;
if (browserId == "F"){
b.tabs[NewTab.id].parent_ttid = b.tabs[activeTabId].parent_ttid;
}
AfterId = activeTabId;
} else { // FAIL, no active tab!
let GroupTabs = GetChildren(b.windows[NewTab.windowId].active_group);
b.tabs[NewTab.id].parent = b.windows[NewTab.windowId].active_group;
if (browserId == "F"){
b.tabs[NewTab.id].parent_ttid = "";
}
if (GroupTabs.length > 0) {
b.tabs[NewTab.id].index = b.tabs[GroupTabs[GroupTabs.length-1]].index+1;
} else {
b.tabs[NewTab.id].index = 0;
}
ParentId = b.windows[NewTab.windowId].active_group;
}
} else {
b.tabs[NewTab.id].parent = "tab_list";
if (browserId == "F"){
b.tabs[NewTab.id].parent_ttid = "";
}
b.tabs[NewTab.id].index = NewTab.index;
ParentId = "tab_list";
}
}
if (opt.append_orphan_tab == "top") {
let GroupTabs = GetChildren(b.windows[NewTab.windowId].active_group);
b.tabs[NewTab.id].parent = b.windows[NewTab.windowId].active_group;
if (browserId == "F"){
b.tabs[NewTab.id].parent_ttid = "";
}
for (let i = 0; i < GroupTabs.length; i++) { // shift all tabs indexes in group
b.tabs[GroupTabs[i]].index += 1;
}
b.tabs[NewTab.id].index = 0;
ParentId = b.windows[NewTab.windowId].active_group;
}
if (opt.append_orphan_tab == "bottom") {
let GroupTabs = GetChildren(b.windows[NewTab.windowId].active_group);
b.tabs[NewTab.id].parent = b.windows[NewTab.windowId].active_group;
if (browserId == "F"){
b.tabs[NewTab.id].parent_ttid = "";
}
if (GroupTabs.length > 0) {
b.tabs[NewTab.id].index = b.tabs[GroupTabs[GroupTabs.length-1]].index+1;
} else {
b.tabs[NewTab.id].index = 0;
}
ParentId = b.windows[NewTab.windowId].active_group;
append = true;
}
}
}
if (opt.move_tabs_on_url_change === "all_new") {
setTimeout(function() {
chrome.tabs.get(NewTab.id, function(CheckTabsUrl) {
AppendTabToGroupOnRegexMatch(CheckTabsUrl.id, CheckTabsUrl.windowId, CheckTabsUrl.url);
});
}, 100);
}
}
setTimeout(function() {
b.schedule_save++;
}, 500);
chrome.runtime.sendMessage({command: "tab_created", windowId: NewTab.windowId, tabId: NewTab.id, tab: NewTab, ParentId: ParentId, InsertAfterId: AfterId, Append: append});
if (b.NewTabsQueue.indexOf(NewTab.id) != -1) {
b.NewTabsQueue.splice(b.NewTabsQueue.indexOf(NewTab.id), 1);
}
});
} else {
console.log("tab_created in queue");
setTimeout(function() {
OnMessageTabCreated(tabId, activeTabId);
}, 100);
}
}

View File

@ -2,7 +2,7 @@
"manifest_version": 2,
"default_locale": "en",
"background": {
"scripts": [ "listeners_bg.js", "scripts/common.js", "background.js" ],
"scripts": [ "global.js", "./scripts/preferences.js", "background_firefox.js", "background_opera.js", "background_vivaldi.js", "background.js" ],
"persistent": true
},
"name": "Tree Tabs",
@ -14,8 +14,7 @@
"19": "icons/16.png",
"16": "icons/16.png"
},
"permissions": [ "<all_urls>", "tabs", "sessions", "storage", "unlimitedStorage", "bookmarks", "tabHide" ],
"permissions": [ "tabs", "sessions", "storage", "unlimitedStorage", "bookmarks", "tabHide" ],
"sidebar_action": {
"default_icon": {
"16": "icons/16.png",
@ -29,21 +28,25 @@
"browser_action": {
"default_icon": "icons/24.png"
},
"applications": {
"gecko": {
"id": "TreeTabs@jagiello.it",
"strict_min_version": "57.0"
}
},
"options_ui": {
"page": "options.html",
"open_in_tab": true
},
"commands": {
"_execute_browser_action": {
"suggested_key": { "default": "F1" },
"description": "toggle Tree Tabs"
},
"close_tree": {
"suggested_key": { "default": "Alt+W" },
"description": "close tree"
}
},
"version": "100"
"applications": {
"gecko": {
"id": "TreeTabs@jagiello.it",
"strict_min_version": "63.0"
}
},
"options_ui": {
"page": "options/options.html",
"open_in_tab": true
},
"version": "1.8.7"
}

View File

@ -1,858 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_0.css" id="sizes_preset_0" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_1.css" id="sizes_preset_1" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_2.css" id="sizes_preset_2" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_3.css" id="sizes_preset_3" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_4.css" id="sizes_preset_4" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_tabs_margin_0.css" id="tabs_margin_0" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_tabs_margin_1.css" id="tabs_margin_1" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_tabs_margin_2.css" id="tabs_margin_2" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_colors.css" id="theme_colors" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme.css" id="theme" />
<link type="text/css" rel="stylesheet" media="all" href="options/options.css" id="main_body_css" />
<style rel="stylesheet"> #red_higlights_go_here { background-color: transparent; } </style>
<link type="text/css" rel="stylesheet" media="all" href="options/options overwrite.css" id="overwrite" />
</head>
<body id="body" class="options_body">
<div style="width:850px; align:left;"><span style="width:100%; font-size:20px; display:inline-block; text-align:center; ">Tree Tabs</span></div>
<br>
<fieldset class="field" id="field_vivaldi" style="display:none;">
<legend class="label" id="options_vivaldi"></legend>
<table>
<tr>
<td class="label" id="opt_url_for_web_panel"></td>
<td><input style="position:relative;width:450px;left:8px;" type="text" id="url_for_web_panel" value=""></input></td>
<td><div style="position:relative; width:20px; height: 20px; left:8px; background-size: 20px 20px; background-image: url(options/options_copy_icon.png);" id="copy_vivaldi_url_for_web_panel" ></div></td>
</tr>
</table>
</fieldset>
<fieldset class="field" id="field_pins">
<legend class="label" id="options_pinned" ></legend>
<table style="display:inline-block;">
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="pin_list_multi_row"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_pin_list_multi_row"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="allow_pin_close"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="option_allow_pin_close"></td>
</tr>
</table>
</fieldset>
<fieldset class="field" id="field_groups">
<legend class="label" id="options_groups"></legend>
<table style="display:vinline-block;">
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="groups_toolbar_default"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_groups_toolbar_default"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="show_counter_groups"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_show_counter_groups"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="syncro_tabbar_groups_tabs_order"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_syncro_tabbar_groups_tabs_order"></td>
</tr>
<tr id="firefox_option_hide_other_groups_tabs_firefox">
<td><input type="checkbox" class="opt_checkbox bg_opt" id="hide_other_groups_tabs_firefox"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_hide_other_groups_tabs_firefox"></td>
</tr>
</table>
<ul>
<li>
<label class="label" id="options_midclick_group"></label>
<select id="midclick_group">
<option class="bg_opt_drop_down_menu" id="options_action_group_none" value="nothing"></option>
<option class="bg_opt_drop_down_menu" id="options_action_group_new" value="new_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_group_undo_close_tab" value="undo_close_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_group_activate_previous_active" value="activate_previous_active"></option>
</select>
</li>
<li>
<label class="label" id="options_dbclick_group"></label>
<select id="dbclick_group">
<option class="bg_opt_drop_down_menu" id="options_action_group_none" value="nothing"></option>
<option class="bg_opt_drop_down_menu" id="options_action_group_new" value="new_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_group_undo_close_tab" value="undo_close_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_group_activate_previous_active" value="activate_previous_active"></option>
</select>
</li>
</ul>
</fieldset>
<fieldset class="field" id="field_folders">
<legend class="label" id="options_folders"></legend>
<ul>
<li>
<label class="label" id="options_midclick_folder"></label>
<select id="midclick_folder">
<option class="bg_opt_drop_down_menu" id="options_action_folder_none" value="nothing"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_rename" value="rename_folder"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_new_folder" value="new_folder"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_new_tab" value="new_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_expand_collapse" value="expand_collapse"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_close" value="close_folder"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_unload" value="unload_folder"></option>
</select>
</li>
<li>
<label class="label" id="options_dbclick_folder"></label>
<select id="dbclick_folder">
<option class="bg_opt_drop_down_menu" id="options_action_folder_none" value="nothing"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_rename" value="rename_folder"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_new_folder" value="new_folder"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_new_tab" value="new_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_expand_collapse" value="expand_collapse"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_close" value="close_folder"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_unload" value="unload_folder"></option>
</select>
</li>
</ul>
<table style="display:vinline-block;">
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="max_tree_drag_drop_folders"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_max_tree_drag_drop_folders"></td>
</tr>
</table>
</fieldset>
<fieldset class="field" id="field_tabs">
<legend class="label" id="options_tabs"></legend>
<ul>
<li>
<label class="label" id="options_midclick_tab"></label>
<select id="midclick_tab">
<option class="bg_opt_drop_down_menu" id="options_action_tab_none" value="nothing"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_new" value="new_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_expand_collapse" value="expand_collapse"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_close" value="close_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_undo_close" value="undo_close_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_reload" value="reload_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_unload" value="unload_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_activate_previous_active" value="activate_previous_active"></option>
</select>
</li>
<li>
<label class="label" id="options_dbclick_tab"></label>
<select id="dbclick_tab">
<option class="bg_opt_drop_down_menu" id="options_action_tab_none" value="nothing"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_new" value="new_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_expand_collapse" value="expand_collapse"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_close" value="close_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_undo_close" value="undo_close_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_reload" value="reload_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_activate_previous_active" value="activate_previous_active"></option>
</select>
</li>
</ul>
<table style="display:vinline-block;">
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="syncro_tabbar_tabs_order"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_syncro_tabbar_tabs_order"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="switch_with_scroll"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_switch_with_scroll"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="orphaned_tabs_to_ungrouped"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_orphaned_tabs_to_ungrouped"></td>
</tr>
</table>
<ul>
<li>
<label class="label" id="options_append_child_tab"></label>
<select id="append_child_tab">
<option class="bg_opt_drop_down_menu" id="options_append_child_tab_top" value="top"></option>
<option class="bg_opt_drop_down_menu" id="options_append_child_tab_bottom" value="bottom"></option>
<option class="bg_opt_drop_down_menu" id="options_append_child_tab_after" value="after"></option>
</select>
</li>
<li id="append_child_tab_after_limit_dropdown">
<label class="label" id="options_append_child_tab_after_limit"></label>
<select id="append_child_tab_after_limit">
<option class="bg_opt_drop_down_menu" id="options_append_child_tab_after_limit_top" value="top"></option>
<option class="bg_opt_drop_down_menu" id="options_append_child_tab_after_limit_after" value="after"></option>
<option class="bg_opt_drop_down_menu" id="options_append_child_tab_after_limit_bottom" value="bottom"></option>
</select>
</li>
<li>
<label class="label" id="options_append_orphan_tab"></label>
<select id="append_orphan_tab">
<option class="bg_opt_drop_down_menu" id="options_append_orphan_tab_top" value="top"></option>
<option class="bg_opt_drop_down_menu" id="options_append_orphan_tab_after_active" value="after_active"></option>
<option class="bg_opt_drop_down_menu" id="options_append_orphan_tab_bottom" value="bottom"></option>
<option class="bg_opt_drop_down_menu" id="options_append_orphan_tab_as_child" value="as_child"></option>
</select>
</li>
<li>
<label class="label" id="options_toolbar_new_tab"></label>
<select id="append_tab_from_toolbar">
<option class="bg_opt_drop_down_menu" id="options_toolbar_new_tab_as_regular_orphan" value="as_regular_orphan"></option>
<option class="bg_opt_drop_down_menu" id="options_toolbar_new_tab_root_of_group" value="group_root"></option>
</select>
</li>
<li>
<label class="label" id="options_after_closing_active_tab"></label>
<select id="after_closing_active_tab">
<option class="bg_opt_drop_down_menu" id="options_after_closing_active_tab_go_up" value="above"></option>
<option class="bg_opt_drop_down_menu" id="options_after_closing_active_tab_go_down" value="below"></option>
<option class="bg_opt_drop_down_menu" id="options_after_closing_active_tab_go_up_seek_in_parent" value="above_seek_in_parent"></option>
<option class="bg_opt_drop_down_menu" id="options_after_closing_active_tab_go_down_seek_in_parent" value="below_seek_in_parent"></option>
<option class="bg_opt_drop_down_menu" id="options_after_closing_active_tab_go_browser" value="browser"></option>
</select>
</li>
<li>
<label class="label" id="options_tab_group_regex"></label><br>
<br><span class="regexLabel">
<label class="label" id="option_tab_match"></label>
</span>
<span class="regexLabel">
<label class="label" id="option_tab_group" style="width:200px"></label>
</span>
<div id="tab_group_regexes"></div>
<button class="set_button" type="button" id="add_tab_group_regex" style="margin:6px;"></button>
</li>
<li>
<label class="label" id="options_move_on_url_change"></label>
<select id="move_tabs_on_url_change">
<option class="bg_opt_drop_down_menu" id="options_move_on_url_change_never" value="never"></option>
<option class="bg_opt_drop_down_menu" id="options_move_on_url_change_from_empty" value="from_empty"></option>
<option class="bg_opt_drop_down_menu" id="options_move_on_url_change_from_empty_b" value="from_empty_b"></option>
<option class="bg_opt_drop_down_menu" id="options_move_on_url_change_all_new" value="all_new"></option>
<option class="bg_opt_drop_down_menu" id="options_move_on_url_change_always" value="always"></option>
</select>
</li>
</ul>
<table style="display:vinline-block;">
<tr>
<td>
<input type="number" style="width:80px;" min="-1" max="9999" step="1" id="max_tree_depth"></input>
</td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_max_tree_depth"></td>
</tr>
</table>
<table style="display:vinline-block;">
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="max_tree_drag_drop"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_max_tree_drag_drop"></td>
</tr>
</table>
<br>
<p style="font-size:11px; color: red;" class="hint_explanation" id="hint_orphan_tab"></p>
<ul style="list-style-type:disc; font-size:11px;">
<li class="hint_explanation" id="hint_ctrl_t"></li>
<li class="hint_explanation" id="hint_from_pin"></li>
<li class="hint_explanation" id="hint_from_bookmark"></li>
<li class="hint_explanation" id="hint_from_external_link"></li>
<li class="hint_explanation" id="hint_from_popup"></li>
</ul>
<span style="display:block; font-size:11px; color: red;" class="hint_explanation" id="hint_explained_new_tab_settings"></span>
<span style="display:block; font-size:11px; color: red;" class="hint_explanation" id="hint_explained_orphan_after_active_settings"></span>
<br>
</fieldset>
<fieldset class="field" id="field_global">
<legend class="label" id="options_global"></legend>
<table style="display:vinline-block;">
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="always_show_close"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_always_show_close"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="never_show_close"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_never_show_close"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="collapse_other_trees"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_collapse_other_trees"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="open_tree_on_hover"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_open_tree_on_hover"></td>
</tr>
<tr>
<td style="position:relative;top:-5px;"><input type="checkbox" class="opt_checkbox bg_opt" id="promote_children"></input></td>
<td style="position:relative;top:-5px;left:2px;width:3px;">-</td>
<td class="label" id="options_promote_children"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="promote_children_in_first_child"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_promote_children_in_first_child"></td>
</tr>
<tr>
<td style="position:relative;top:-1px;"><input type="checkbox" class="opt_checkbox bg_opt" id="skip_load"></input></td>
<td style="position:relative;top:-1px;left:2px;width:3px;">-</td>
<td class="label" id="options_skip_load"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="show_counter_tabs"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_show_counter_tabs"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="show_counter_tabs_hints"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_show_counter_tabs_hints"></td>
</tr>
</table>
</fieldset>
<fieldset class="field" id="field_show_toolbar" style="position: relative; width:850px;">
<legend id="toolbar_legend">
<input type="checkbox" class="opt_checkbox bg_opt" style="position:relative; top:-1px;" id="show_toolbar"></input>
<label class="label" style="position:relative; top:-3px;" id="options_toolbar"></label>
</legend>
<label class="label" style="margin-top: 4px;" id="options_available_buttons"></label>
<div id="sample_toolbar_block" style="position:relative; margin: 10px; width: 355px;">
<div id="toolbar_unused_buttons" style="position: relative; background-color: #b8ffbf; height: 30px; width: 788px;"></div>
<div class="toolbar_edit" id="toolbar" style="position: relative; top: 5px; height: 26px; width: 788px; overflow:hidden;"></div>
</div>
<button class="set_button" type="button" id="options_reset_toolbar_button" style="margin:10px; margin-top:20px;">Reset</button>
</fieldset>
<fieldset class="field" id="field_theme" style="width:850px;">
<legend class="label" id="options_theme"></legend>
<select id="theme_list" style="padding-right:6px;"></select>
<input type="text" id="new_theme_name" name="untitled" value="untitled"></input>
<button class="set_button theme_buttons" type="button" id="options_rename_theme_button" style="margin:6px;">Rename</button>
<button class="set_button theme_buttons" type="button" id="options_add_theme_button" style="margin:6px;">Add new</button>
<button class="set_button theme_buttons" type="button" id="options_remove_theme_button" style="margin:6px;">Remove</button>
<button class="set_button theme_buttons" type="button" id="options_import_theme_button" style="margin:6px;">Import</button>
<button class="set_button theme_buttons" type="button" id="options_export_theme_button" style="margin:6px;">Export</button>
<button class="set_button theme_buttons" type="button" id="options_share_theme_link" style="margin:6px;">Export</button>
<br>
<br>
<fieldset class="field" id="options_toolbar_look" style="position: relative; width:816px;">
<legend id="toolbar_legend">
<label class="label" id="options_toolbar_look"></label>
</legend>
<div id="sample_toolbar_block" style="position:relative; width: 788px; margin: 10px;">
<div id="toolbar_colors_pick_block" style="position: relative; width: 788px; height: 26px;">
<div class="pick_col color_bucket" id="button_background" ></div>
<div class="pick_col color_bucket" id="button_hover_background" ></div>
<div class="pick_col color_bucket" id="button_on_background" ></div>
<div class="spacer"></div>
<div class="pick_col color_toolbar_icon" id="button_icons" ></div>
<div class="pick_col color_toolbar_icon" id="button_icons_hover" ></div>
<div class="pick_col color_toolbar_icon" id="button_on_icons" ></div>
<div class="spacer"></div>
<div class="pick_col color_border" id="button_border" ></div>
<div class="pick_col color_border" id="button_hover_border" ></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="pick_col font_color" id="filter_box_font" ></div>
<div class="pick_col color_bucket" id="filter_box_background" ></div>
<div class="pick_col color_border" id="filter_box_border" ></div>
<div class="pick_col color_x" id="filter_clear_icon" ></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="pick_col color_bucket" id="toolbar_background" ></div>
<div class="pick_col color_bucket" id="toolbar_shelf_background" ></div>
<div class="pick_col color_border" id="toolbar_border_bottom" ></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="pick_col color_bucket" id="button_shelf_background" ></div>
<div class="pick_col color_bucket" id="button_shelf_hover_background" ></div>
<div class="spacer"></div>
<div class="pick_col color_toolbar_icon" id="button_shelf_icons" ></div>
<div class="pick_col color_toolbar_icon" id="button_shelf_icons_hover" ></div>
<div class="spacer"></div>
<div class="pick_col color_border" id="button_shelf_border" ></div>
<div class="pick_col color_border" id="button_shelf_hover_border" ></div>
</div>
<div class="toolbar" id="toolbar_theme" style="position: relative; top: 5px; height: 53px; width: 788px; overflow:hidden;">
<div id="toolbar_main_theme">
<div class="button_theme" id="button_theme_plus"><div class="button_img_theme" id="button_theme_plus_img"></div></div>
<div class="button_theme" id="button_theme_search"><div class="button_img_theme" id="button_theme_search_img"></div></div>
</div>
<div id="toolbar_search_input_box_theme">
<input id="filter_box_theme" type="text" placeholder="Search tabs..."></input>
<div id="button_filter_clear_theme" style="position:absolute;" type="reset"></div>
<div class="button_shelf_theme" id="button_theme_pen"><div class="button_img_shelf_theme" id="button_theme_pen_img"></div></div>
</div>
</div>
</div>
</fieldset>
<fieldset class="field" id="Tabs" style="position: relative; top: 6px; width:816px; height: 950px;">
<legend class="label" id="options_theme_tabs"></legend>
<div id="tabs_options_block">
<div id="ff_folder1" class="tab_color_options_row">
<div class="pick_col color_bucket" id="folder_icon_open"></div>
</div>
<div id="ff_folder2" class="tab_color_options_row">
<div class="pick_col color_bucket" id="folder_icon_closed"></div>
</div>
<div id="ff_folder3" class="tab_color_options_row">
<div class="pick_col color_bucket" id="folder_icon_hover"></div>
</div>
<div id="t2" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_background"></div>
<div class="tab_col pick_col color_border" id="tab_border"></div>
</div>
<div id="t11" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_hover_border"></div>
<div class="pick_col color_x" id="close_x"></div>
</div>
<div id="t12" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_selected_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_selected_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_selected_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_selected_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_selected_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_selected_background"></div>
<div class="tab_col pick_col color_border" id="tab_selected_border"></div>
</div>
<div id="t13" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_selected_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_selected_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_selected_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_selected_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_selected_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_selected_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_selected_hover_border"></div>
<div class="pick_col color_x" id="close_hover_x"></div>
<div class="pick_col color_border" id="close_hover_border"></div>
<div class="pick_col color_bucket" id="close_hover_background"></div>
</div>
<div id="t3" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_active_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_active_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_active_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_active_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_active_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_active_background"></div>
<div class="tab_col pick_col color_border" id="tab_active_border"></div>
</div>
<div id="t15" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_active_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_active_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_active_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_active_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_active_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_active_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_active_hover_border"></div>
</div>
<div id="t14" class="tab_color_options_row">
<div class="pick_col color_bucket" id="expand_closed_background"></div>
<div class="tab_col pick_col font_color" id="tab_active_selected_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_active_selected_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_active_selected_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_active_selected_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_active_selected_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_active_selected_background"></div>
<div class="tab_col pick_col color_border" id="tab_active_selected_border"></div>
</div>
<div id="t16" class="tab_color_options_row">
<div class="pick_col color_bucket" id="expand_hover_background"></div>
<div class="tab_col pick_col font_color" id="tab_selected_active_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_selected_active_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_selected_active_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_selected_active_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_selected_active_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_selected_active_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_selected_active_hover_border"></div>
</div>
<div id="t5" class="tab_color_options_row">
<div class="pick_col color_bucket" id="expand_open_background"></div>
<div class="tab_col pick_col font_color" id="tab_discarded_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_discarded_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_discarded_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_discarded_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_discarded_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_discarded_background"></div>
<div class="tab_col pick_col color_border" id="tab_discarded_border"></div>
</div>
<div id="t17" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_discarded_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_discarded_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_discarded_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_discarded_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_discarded_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_discarded_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_discarded_hover_border"></div>
</div>
<div id="t19" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_selected_discarded_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_selected_discarded_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_selected_discarded_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_selected_discarded_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_selected_discarded_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_selected_discarded_background"></div>
<div class="tab_col pick_col color_border" id="tab_selected_discarded_border"></div>
<div class="pick_col color_bucket" id="drag_indicator"></div>
</div>
<div id="t20" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_selected_discarded_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_selected_discarded_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_selected_discarded_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_selected_discarded_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_selected_discarded_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_selected_discarded_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_selected_discarded_hover_border"></div>
</div>
<div id="t6" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_border"></div>
</div>
<div id="t21" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_hover_border"></div>
</div>
<div id="t22" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_active_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_active_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_active_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_active_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_active_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_active_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_active_border"></div>
</div>
<div id="t23" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_active_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_active_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_active_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_active_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_active_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_active_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_active_hover_border"></div>
</div>
<div id="t8" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_border"></div>
</div>
<div id="t18" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_hover_border"></div>
</div>
<div id="t25" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_active_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_active_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_active_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_active_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_active_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_active_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_active_border"></div>
</div>
<div id="t26" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_active_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_active_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_active_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_active_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_active_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_active_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_active_hover_border"></div>
</div>
<div id="t30" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_highlighted_search_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_highlighted_search_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_highlighted_search_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_highlighted_search_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_highlighted_search_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_highlighted_search_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_highlighted_search_border"></div>
</div>
<div id="t31" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_highlighted_search_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_highlighted_search_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_highlighted_search_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_highlighted_search_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_highlighted_search_hover_border"></div>
</div>
<div id="t32" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_active_highlighted_search_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_active_highlighted_search_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_active_highlighted_search_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_active_highlighted_search_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_active_highlighted_search_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_active_highlighted_search_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_active_highlighted_search_border"></div>
</div>
<div id="t33" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_active_highlighted_search_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_active_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_active_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_active_highlighted_search_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_active_highlighted_search_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_active_highlighted_search_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_active_highlighted_search_hover_border"></div>
</div>
<div id="t34" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_highlighted_search_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_highlighted_search_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_highlighted_search_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_highlighted_search_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_highlighted_search_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_highlighted_search_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_highlighted_search_border"></div>
</div>
<div id="t35" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_highlighted_search_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_highlighted_search_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_highlighted_search_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_highlighted_search_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_highlighted_search_hover_border"></div>
</div>
<div id="t36" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_active_highlighted_search_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_active_highlighted_search_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_active_highlighted_search_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_active_highlighted_search_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_active_highlighted_search_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_active_highlighted_search_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_active_highlighted_search_border"></div>
</div>
<div id="t37" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_active_highlighted_search_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_active_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_active_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_active_highlighted_search_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_active_highlighted_search_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_active_highlighted_search_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_active_highlighted_search_hover_border"></div>
</div>
</div>
<div id="scrollbar_size_indicator">
<div class="options_button_minus" id="options_tab_list_scrollbar_width_down"></div>
<div class="options_button_plus" id="options_tab_list_scrollbar_width_up"></div>
<div class="options_button_minus" id="options_tab_list_scrollbar_height_down"></div>
<div class="options_button_plus" id="options_tab_list_scrollbar_height_up"></div>
</div>
<div class="pick_col color_bucket" id="scrollbar_thumb"></div>
<div class="pick_col color_bucket pick_col_hover" id="scrollbar_thumb_hover"></div>
<div class="pick_col color_bucket" id="scrollbar_track"></div>
<div class="pin_list" id="pin_list"></div>
<div id="groups">
<div class="group" id="tab_list">
<div class="children_folders" id="cftab_list"></div>
<div class="children_tabs" id="cttab_list"></div>
</div>
</div>
<div id="pin_list_scrollbar"><div id="pin_list_scrollbar_thumb"></div></div>
<div id="group_scrollbar"><div id="group_scrollbar_thumb"></div></div>
<div class="pick_col color_bucket" id="group_list_background"></div>
<div class="pick_col color_border" id="group_list_borders"></div>
<div class="pick_col color_bucket pick_col_hover" id="group_list_button_hover_background"></div>
<div class="pick_col font_color" id="group_list_default_font_color"></div>
<div id="toolbar_groups_block">
<div class="scroll_group" id="scroll_group_up"></div>
<div class="group_list" id="group_list"></div>
<div class="scroll_group" id="scroll_group_down"></div>
</div>
<div id="options_tabs_margins_indicator">
<form action="" id="tabs_margin_spacing" style="position:absolute; left:4px; top:12px;">
<input type="radio" class="tabs_margin_spacing" id="options_tabs_margin_overlap" name="tabs_margin_spacing" value="overlap"></input>
<input type="radio" class="tabs_margin_spacing" id="options_tabs_margin_0" name="tabs_margin_spacing" value="no_space"></input>
<input type="radio" class="tabs_margin_spacing" id="options_tabs_margin_1" name="tabs_margin_spacing" value="1px_space"></input>
</form>
</div>
<div id="options_tabs_indentation_indicator">
<div class="options_button_minus" id="options_tabs_indentation_down"></div>
<div class="options_button_plus" id="options_tabs_indentation_up"></div>
</div>
<div id="options_tabs_roundness_indicator">
<div class="options_button_minus" id="options_tabs_roundness_down"></div>
<div class="options_button_plus" id="options_tabs_roundness_up"></div>
</div>
<div id="options_tabs_size_indicator">
<div class="options_button_minus" id="options_tabs_size_down"></div>
<div class="options_button_plus" id="options_tabs_size_up"></div>
</div>
<div id="pin_list_options_block">
<div class="pick_col color_bucket" id="attention_background"></div>
<div class="pick_col color_border" id="attention_border"></div>
<div class="pick_col color_border" id="pin_list_border_bottom"></div>
<div class="pick_col color_bucket" id="pin_list_background"></div>
</div>
<div class="pick_col color_bucket" id="tab_list_background"></div>
</fieldset>
<fieldset class="field" style="width:816px;">
<legend class="label" id="options_menu"></legend>
<div id="menu_options_block" style="position:relative; top:0px; left:10px;">
<div class="pick_col color_border" id="tabs_menu_border"></div>
<div class="pick_col color_bucket" id="tabs_menu_background"></div>
<div class="pick_col font_color" id="tabs_menu_font"></div>
<div class="pick_col color_border" id="tabs_menu_hover_border"></div>
<div class="pick_col color_bucket" id="tabs_menu_hover_background"></div>
<div class="pick_col color_border" id="tabs_menu_separator"></div>
</div>
<ul class="menu" id="tabs_menu" style="display:inline-block;position:relative;top:0px;left:10px;">
<li class="menu_item" id="menu_hover_sample"></li>
<div class="separator" id="menu_separator1"></div>
<li class="menu_item" id="menu_sample1"></li>
<div class="separator" id="menu_separator2"></div>
<li class="menu_item" id="menu_sample2"></li>
</ul>
</fieldset>
</fieldset>
<fieldset class="field"">
<legend class="label" id="options_development"></legend>
<table style="display:inline-block;">
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="debug"></input></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_debug"></td>
</tr>
</table>
<br>
<button class="set_button" type="button" id="options_export_debug" style="position: relative; margin:10px;"></button>
<button class="set_button" type="button" id="options_print_debug" style="position: relative; margin:10px;"></button>
</fieldset>
<button class="set_button" type="button" id="options_clear_data" style="margin:10px;"></button>
<input type="color" id="color_picker" style="position:absolute; left:-1000px; top:-1000px; width:1px; height:1px; overflow:hidden;">
<div id="DragImage" style="display: none; width:0px; height:0px;"></div>
<script type="text/javascript" src="scripts/common.js"></script>
<script type="text/javascript" src="scripts/utils.js"></script>
<script type="text/javascript" src="scripts/toolbar.js"></script>
<script type="text/javascript" src="scripts/tabs.js"></script>
<script type="text/javascript" src="scripts/groups.js"></script>
<script type="text/javascript" src="scripts/folders.js"></script>
<script type="text/javascript" src="scripts/theme.js"></script>
<script type="text/javascript" src="options/sample_tabs.js"></script>
<script type="text/javascript" src="options/options.js"></script>
<div id="donate"></div>
<div id="donate_paypal" class="donation_button"></div>
<div id="donate_litecoin" class="donation_button"></div>
<div id="donate_bitcoin" class="donation_button"></div>
<div id="donate_ethereum" class="donation_button"></div>
</body>
</html>

View File

@ -425,7 +425,7 @@ ul:not(.menu) li {
/* TAB LIST AND SCROLLBAR */
#groups {
position: absolute;
height: 850px;
height: calc(100% - var(--pin_height) - 80px);
width: calc(771px - var(--scrollbar_width));
top: calc(var(--scrollbar_height) + var(--pin_height) + 33px);
left: 40px;
@ -434,7 +434,7 @@ ul:not(.menu) li {
#group_scrollbar {
position: absolute;
height: 850px;
height: calc(100% - var(--pin_height) - 80px);
width: var(--scrollbar_width);
top: calc(var(--scrollbar_height) + var(--pin_height) + 33px);
left: calc(810px - var(--scrollbar_width));
@ -602,7 +602,7 @@ ul:not(.menu) li {
left: 20px;
top: calc(var(--scrollbar_height) + var(--pin_height) + 33px);
width: 19px;
height: 850px;
height: calc(100% - var(--pin_height) - 80px);
background-color: var(--group_list_background);
border-right: 1px solid var(--group_list_borders);
overflow: visible;

905
options/options.html Normal file
View File

@ -0,0 +1,905 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link type="text/css" rel="stylesheet" media="all" href="../theme/theme_size_preset_0.css" id="sizes_preset_0" />
<link type="text/css" rel="stylesheet" media="all" href="../theme/theme_size_preset_1.css" id="sizes_preset_1" />
<link type="text/css" rel="stylesheet" media="all" href="../theme/theme_size_preset_2.css" id="sizes_preset_2" />
<link type="text/css" rel="stylesheet" media="all" href="../theme/theme_size_preset_3.css" id="sizes_preset_3" />
<link type="text/css" rel="stylesheet" media="all" href="../theme/theme_size_preset_4.css" id="sizes_preset_4" />
<link type="text/css" rel="stylesheet" media="all" href="../theme/theme_size_preset_5.css" id="sizes_preset_5" />
<link type="text/css" rel="stylesheet" media="all" href="../theme/theme_tabs_margin_0.css" id="tabs_margin_0" />
<link type="text/css" rel="stylesheet" media="all" href="../theme/theme_tabs_margin_1.css" id="tabs_margin_1" />
<link type="text/css" rel="stylesheet" media="all" href="../theme/theme_tabs_margin_2.css" id="tabs_margin_2" />
<link type="text/css" rel="stylesheet" media="all" href="../theme/theme_colors.css" id="theme_colors" />
<link type="text/css" rel="stylesheet" media="all" href="../theme/theme.css" id="theme" />
<link type="text/css" rel="stylesheet" media="all" href="../theme/theme_blinking_attention.css" id="blinking_pins" />
<link type="text/css" rel="stylesheet" media="all" href="../theme/theme_blinking_audio.css" id="blinking_audio" />
<link type="text/css" rel="stylesheet" media="all" href="./options.css" id="main_body_css" />
<style rel="stylesheet">
#red_higlights_go_here {
background-color: transparent;
}
</style>
<link type="text/css" rel="stylesheet" media="all" href="./options_overwrite.css" id="overwrite" />
</head>
<body id="body" class="options_body">
<div style="width:850px; align:left;"><span style="width:100%; font-size:20px; display:inline-block; text-align:center;">Tree Tabs</span></div>
<br>
<fieldset class="field" id="field_vivaldi" style="display:none;">
<legend class="label" id="options_vivaldi"></legend>
<table>
<tr>
<td class="label" id="opt_url_for_web_panel"></td>
<td><input style="position:relative;width:450px;left:8px;" type="text" id="url_for_web_panel" value=""/></td>
<td><div style="position:relative; width:20px; height: 20px; left:8px; background-size: 20px 20px; background-image: url(./options_copy_icon.png);" id="copy_vivaldi_url_for_web_panel" ></div></td>
</tr>
</table>
</fieldset>
<fieldset class="field" id="field_pins">
<legend class="label" id="options_pinned" ></legend>
<table style="display:inline-block;">
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="pin_list_multi_row"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_pin_list_multi_row"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="allow_pin_close"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="option_allow_pin_close"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="pin_attention_blinking"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="option_pin_attention_blinking"></td>
</tr>
</table>
</fieldset>
<fieldset class="field" id="field_groups">
<legend class="label" id="options_groups"></legend>
<table style="display:vinline-block;">
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="groups_toolbar_default"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_groups_toolbar_default"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="show_counter_groups"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_show_counter_groups"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="syncro_tabbar_groups_tabs_order"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_syncro_tabbar_groups_tabs_order"></td>
</tr>
<tr id="firefox_option_hide_other_groups_tabs_firefox">
<td><input type="checkbox" class="opt_checkbox bg_opt" id="hide_other_groups_tabs_firefox"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_hide_other_groups_tabs_firefox"></td>
</tr>
</table>
<ul>
<li>
<label class="label" id="options_midclick_group"></label>
<select id="midclick_group">
<option class="bg_opt_drop_down_menu" id="options_action_group_none" value="nothing"></option>
<option class="bg_opt_drop_down_menu" id="options_action_group_new" value="new_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_group_undo_close_tab" value="undo_close_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_group_activate_previous_active" value="activate_previous_active"></option>
</select>
</li>
<li>
<label class="label" id="options_dbclick_group"></label>
<select id="dbclick_group">
<option class="bg_opt_drop_down_menu" id="options_action_group_none" value="nothing"></option>
<option class="bg_opt_drop_down_menu" id="options_action_group_new" value="new_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_group_undo_close_tab" value="undo_close_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_group_activate_previous_active" value="activate_previous_active"></option>
</select>
</li>
</ul>
</fieldset>
<fieldset class="field" id="field_folders">
<legend class="label" id="options_folders"></legend>
<ul>
<li>
<label class="label" id="options_midclick_folder"></label>
<select id="midclick_folder">
<option class="bg_opt_drop_down_menu" id="options_action_folder_none" value="nothing"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_rename" value="rename_folder"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_new_folder" value="new_folder"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_new_tab" value="new_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_expand_collapse" value="expand_collapse"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_close" value="close_folder"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_unload" value="unload_folder"></option>
</select>
</li>
<li>
<label class="label" id="options_dbclick_folder"></label>
<select id="dbclick_folder">
<option class="bg_opt_drop_down_menu" id="options_action_folder_none" value="nothing"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_rename" value="rename_folder"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_new_folder" value="new_folder"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_new_tab" value="new_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_expand_collapse" value="expand_collapse"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_close" value="close_folder"></option>
<option class="bg_opt_drop_down_menu" id="options_action_folder_unload" value="unload_folder"></option>
</select>
</li>
</ul>
<!--
<table style="display:vinline-block;">
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="max_tree_drag_drop_folders"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_max_tree_drag_drop_folders"></td>
</tr>
</table>
-->
</fieldset>
<fieldset class="field" id="field_tabs">
<legend class="label" id="options_tabs"></legend>
<ul>
<li>
<label class="label" id="options_midclick_tab"></label>
<select id="midclick_tab">
<option class="bg_opt_drop_down_menu" id="options_action_tab_none" value="nothing"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_new" value="new_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_expand_collapse" value="expand_collapse"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_close" value="close_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_undo_close" value="undo_close_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_reload" value="reload_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_unload" value="unload_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_activate_previous_active" value="activate_previous_active"></option>
</select>
</li>
<li>
<label class="label" id="options_dbclick_tab"></label>
<select id="dbclick_tab">
<option class="bg_opt_drop_down_menu" id="options_action_tab_none" value="nothing"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_new" value="new_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_expand_collapse" value="expand_collapse"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_close" value="close_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_undo_close" value="undo_close_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_reload" value="reload_tab"></option>
<option class="bg_opt_drop_down_menu" id="options_action_tab_activate_previous_active" value="activate_previous_active"></option>
</select>
</li>
</ul>
<table style="display:vinline-block;">
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="syncro_tabbar_tabs_order"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_syncro_tabbar_tabs_order"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="switch_with_scroll"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_switch_with_scroll"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="orphaned_tabs_to_ungrouped"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_orphaned_tabs_to_ungrouped"></td>
</tr>
</table>
<p style="position: relative; top: -10px; left: 40px; font-size:11px; color: #c71414;" class="hint_explanation" id="hint_orphan_tab"></p>
<ul style="position: relative; top: -14px; left: 30px; list-style-type:disc; font-size:11px; color: #c71414;">
<li class="hint_explanation" id="hint_ctrl_t"></li>
<li class="hint_explanation" id="hint_from_pin"></li>
<li class="hint_explanation" id="hint_from_bookmark"></li>
<li class="hint_explanation" id="hint_from_external_link"></li>
<li class="hint_explanation" id="hint_from_popup"></li>
<li class="hint_explanation" id="hint_explained_new_tab_settings"></li>
</ul>
<ul>
<li>
<label class="label" id="options_append_pinned_tab"></label>
<select id="append_pinned_tab">
<option class="bg_opt_drop_down_menu" id="options_append_pinned_tab_first" value="first"></option>
<option class="bg_opt_drop_down_menu" id="options_append_pinned_tab_after" value="after"></option>
<option class="bg_opt_drop_down_menu" id="options_append_pinned_tab_last" value="last"></option>
</select>
</li>
<li>
<label class="label" id="options_append_child_tab"></label>
<select id="append_child_tab">
<option class="bg_opt_drop_down_menu" id="options_append_child_tab_top" value="top"></option>
<option class="bg_opt_drop_down_menu" id="options_append_child_tab_bottom" value="bottom"></option>
<option class="bg_opt_drop_down_menu" id="options_append_child_tab_after" value="after"></option>
</select>
</li>
<li id="append_child_tab_after_limit_dropdown">
<label class="label" id="options_append_child_tab_after_limit"></label>
<select id="append_child_tab_after_limit">
<option class="bg_opt_drop_down_menu" id="options_append_child_tab_after_limit_top" value="top"></option>
<option class="bg_opt_drop_down_menu" id="options_append_child_tab_after_limit_after" value="after"></option>
<option class="bg_opt_drop_down_menu" id="options_append_child_tab_after_limit_bottom" value="bottom"></option>
</select>
</li>
<li>
<label class="label" id="options_append_orphan_tab"></label>
<select id="append_orphan_tab">
<option class="bg_opt_drop_down_menu" id="options_append_orphan_tab_top" value="top"></option>
<option class="bg_opt_drop_down_menu" id="options_append_orphan_tab_bottom" value="bottom"></option>
<option class="bg_opt_drop_down_menu" id="options_append_orphan_tab_after_active" value="after_active"></option>
<option class="bg_opt_drop_down_menu" id="options_append_orphan_tab_active_parent_top" value="active_parent_top"></option>
<option class="bg_opt_drop_down_menu" id="options_append_orphan_tab_active_parent_bottom" value="active_parent_bottom"></option>
<option class="bg_opt_drop_down_menu" id="options_append_orphan_tab_as_child" value="as_child"></option>
</select>
<span style="position: relative; left: 6px; display:block; font-size:10px; color: #c71414;" class="hint_explanation" id="hint_explained_orphan_after_active_settings"></span>
</li>
<li>
<label class="label" id="options_toolbar_new_tab"></label>
<select id="append_tab_from_toolbar">
<option class="bg_opt_drop_down_menu" id="options_toolbar_new_tab_as_regular_orphan" value="as_regular_orphan"></option>
<option class="bg_opt_drop_down_menu" id="options_toolbar_new_tab_root_of_group" value="group_root"></option>
</select>
</li>
<li>
<label class="label" id="options_after_closing_active_tab"></label>
<select id="after_closing_active_tab">
<option class="bg_opt_drop_down_menu" id="options_after_closing_active_tab_go_up" value="above"></option>
<option class="bg_opt_drop_down_menu" id="options_after_closing_active_tab_go_down" value="below"></option>
<option class="bg_opt_drop_down_menu" id="options_after_closing_active_tab_go_up_seek_in_parent" value="above_seek_in_parent"></option>
<option class="bg_opt_drop_down_menu" id="options_after_closing_active_tab_go_down_seek_in_parent" value="below_seek_in_parent"></option>
<option class="bg_opt_drop_down_menu" id="options_after_closing_active_tab_go_browser" value="browser"></option>
</select>
</li>
<li>
<label class="label" id="options_tab_group_regex"></label><br>
<br><span class="regexLabel">
<label class="label" id="option_tab_match"></label>
</span>
<span class="regexLabel">
<label class="label" id="option_tab_group" style="width:200px"></label>
</span>
<div id="tab_group_regexes"></div>
<button class="set_button" type="button" id="add_tab_group_regex" style="margin:6px;"></button>
</li>
<li>
<label class="label" id="options_move_on_url_change"></label>
<select id="move_tabs_on_url_change">
<option class="bg_opt_drop_down_menu" id="options_move_on_url_change_never" value="never"></option>
<option class="bg_opt_drop_down_menu" id="options_move_on_url_change_from_empty" value="from_empty"></option>
<option class="bg_opt_drop_down_menu" id="options_move_on_url_change_from_empty_b" value="from_empty_b"></option>
<option class="bg_opt_drop_down_menu" id="options_move_on_url_change_all_new" value="all_new"></option>
<option class="bg_opt_drop_down_menu" id="options_move_on_url_change_always" value="always"></option>
</select>
</li>
</ul>
<table style="display:vinline-block;">
<tr>
<td>
<input type="number" style="width:80px;" min="-1" max="9999" step="1" id="max_tree_depth"/>
</td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_max_tree_depth"></td>
</tr>
</table>
<table style="display:vinline-block;">
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="max_tree_drag_drop"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_max_tree_drag_drop"></td>
</tr>
</table>
</fieldset>
<fieldset class="field" id="field_global">
<legend class="label" id="options_global"></legend>
<table style="display:vinline-block;">
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="audio_blinking"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="option_audio_blinking"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="always_show_close"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_always_show_close"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="never_show_close"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_never_show_close"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="collapse_other_trees"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_collapse_other_trees"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="open_tree_on_hover"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_open_tree_on_hover"></td>
</tr>
<tr>
<td style="position:relative;top:-5px;"><input type="checkbox" class="opt_checkbox bg_opt" id="promote_children"/></td>
<td style="position:relative;top:-5px;left:2px;width:3px;">-</td>
<td class="label" id="options_promote_children"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="promote_children_in_first_child"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_promote_children_in_first_child"></td>
</tr>
<tr>
<td style="position:relative;top:-1px;"><input type="checkbox" class="opt_checkbox bg_opt" id="skip_load"/></td>
<td style="position:relative;top:-1px;left:2px;width:3px;">-</td>
<td class="label" id="options_skip_load"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="show_counter_tabs"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_show_counter_tabs"></td>
</tr>
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="show_counter_tabs_hints"/></td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_show_counter_tabs_hints"></td>
</tr>
</table>
</fieldset>
<fieldset class="field" id="field_show_toolbar" style="position: relative; width:850px;">
<legend id="toolbar_legend">
<input type="checkbox" class="opt_checkbox bg_opt" style="position:relative; top:-1px;" id="show_toolbar"/>
<label class="label" style="position:relative; top:-3px;" id="options_toolbar"></label>
</legend>
<label class="label" style="margin-top: 4px;" id="options_available_buttons"></label>
<div id="sample_toolbar_block" style="position:relative; margin: 10px; width: 355px;">
<div id="toolbar_unused_buttons" style="position: relative; background-color: #b8ffbf; height: 30px; width: 788px;"></div>
<div class="toolbar_edit" id="toolbar" style="position: relative; top: 5px; height: 26px; width: 788px; overflow:hidden;"></div>
</div>
<button class="set_button" type="button" id="options_reset_toolbar_button" style="margin:10px; margin-top:20px;">Reset</button>
</fieldset>
<fieldset class="field" id="field_theme" style="width:850px;">
<legend class="label" id="options_theme"></legend>
<select id="theme_list" style="padding-right:6px;"></select>
<input type="text" id="new_theme_name" name="untitled" value="untitled"/>
<button class="set_button theme_buttons" type="button" id="options_rename_theme_button" style="margin:6px;">Rename</button>
<button class="set_button theme_buttons" type="button" id="options_add_theme_button" style="margin:6px;">Add new</button>
<button class="set_button theme_buttons" type="button" id="options_remove_theme_button" style="margin:6px;">Remove</button>
<button class="set_button theme_buttons" type="button" id="options_import_theme_button" style="margin:6px;">Import</button>
<button class="set_button theme_buttons" type="button" id="options_export_theme_button" style="margin:6px;">Export</button>
<button class="set_button theme_buttons" type="button" id="options_share_theme_link" style="margin:6px;">Export</button>
<br>
<br>
<fieldset class="field" id="options_toolbar_look" style="position: relative; width:816px;">
<legend id="toolbar_legend">
<label class="label" id="options_toolbar_look"></label>
</legend>
<div id="sample_toolbar_block" style="position:relative; width: 788px; margin: 10px;">
<div id="toolbar_colors_pick_block" style="position: relative; width: 788px; height: 26px;">
<div class="pick_col color_bucket" id="button_background" ></div>
<div class="pick_col color_bucket" id="button_hover_background" ></div>
<div class="pick_col color_bucket" id="button_on_background" ></div>
<div class="spacer"></div>
<div class="pick_col color_toolbar_icon" id="button_icons" ></div>
<div class="pick_col color_toolbar_icon" id="button_icons_hover" ></div>
<div class="pick_col color_toolbar_icon" id="button_on_icons" ></div>
<div class="spacer"></div>
<div class="pick_col color_border" id="button_border" ></div>
<div class="pick_col color_border" id="button_hover_border" ></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="pick_col font_color" id="filter_box_font" ></div>
<div class="pick_col color_bucket" id="filter_box_background" ></div>
<div class="pick_col color_border" id="filter_box_border" ></div>
<div class="pick_col color_x" id="filter_clear_icon" ></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="pick_col color_bucket" id="toolbar_background" ></div>
<div class="pick_col color_bucket" id="toolbar_shelf_background" ></div>
<div class="pick_col color_border" id="toolbar_border_bottom" ></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="pick_col color_bucket" id="button_shelf_background" ></div>
<div class="pick_col color_bucket" id="button_shelf_hover_background" ></div>
<div class="spacer"></div>
<div class="pick_col color_toolbar_icon" id="button_shelf_icons" ></div>
<div class="pick_col color_toolbar_icon" id="button_shelf_icons_hover" ></div>
<div class="spacer"></div>
<div class="pick_col color_border" id="button_shelf_border" ></div>
<div class="pick_col color_border" id="button_shelf_hover_border" ></div>
</div>
<div class="toolbar" id="toolbar_theme" style="position: relative; top: 5px; height: 53px; width: 788px; overflow:hidden;">
<div id="toolbar_main_theme">
<div class="button_theme" id="button_theme_plus"><div class="button_img_theme" id="button_theme_plus_img"></div></div>
<div class="button_theme" id="button_theme_search"><div class="button_img_theme" id="button_theme_search_img"></div></div>
</div>
<div id="toolbar_search_input_box_theme">
<input id="filter_box_theme" type="text" placeholder="Search tabs..."/>
<div id="button_filter_clear_theme" style="position:absolute;" type="reset"></div>
<div class="button_shelf_theme" id="button_theme_pen"><div class="button_img_shelf_theme" id="button_theme_pen_img"></div></div>
</div>
</div>
</div>
</fieldset>
<fieldset class="field" id="Tabs" style="position: relative; top: 6px; width:816px; height: 1050px;">
<legend class="label" id="options_theme_tabs"></legend>
<div id="tabs_options_block">
<div id="ff_folder1" class="tab_color_options_row">
<div class="pick_col color_bucket" id="folder_icon_open"></div>
</div>
<div id="ff_folder2" class="tab_color_options_row">
<div class="pick_col color_bucket" id="folder_icon_closed"></div>
</div>
<div id="ff_folder3" class="tab_color_options_row">
<div class="pick_col color_bucket" id="folder_icon_hover"></div>
</div>
<div id="t2" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_background"></div>
<div class="tab_col pick_col color_border" id="tab_border"></div>
</div>
<div id="t11" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_hover_border"></div>
<div class="pick_col color_x" id="close_x"></div>
</div>
<div id="t12" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_selected_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_selected_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_selected_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_selected_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_selected_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_selected_background"></div>
<div class="tab_col pick_col color_border" id="tab_selected_border"></div>
</div>
<div id="t13" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_selected_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_selected_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_selected_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_selected_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_selected_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_selected_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_selected_hover_border"></div>
<div class="pick_col color_x" id="close_hover_x"></div>
<div class="pick_col color_border" id="close_hover_border"></div>
<div class="pick_col color_bucket" id="close_hover_background"></div>
</div>
<div id="t3" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_active_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_active_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_active_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_active_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_active_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_active_background"></div>
<div class="tab_col pick_col color_border" id="tab_active_border"></div>
</div>
<div id="t15" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_active_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_active_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_active_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_active_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_active_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_active_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_active_hover_border"></div>
</div>
<div id="t14" class="tab_color_options_row">
<div class="pick_col color_bucket" id="expand_closed_background"></div>
<div class="tab_col pick_col font_color" id="tab_active_selected_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_active_selected_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_active_selected_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_active_selected_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_active_selected_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_active_selected_background"></div>
<div class="tab_col pick_col color_border" id="tab_active_selected_border"></div>
</div>
<div id="t16" class="tab_color_options_row">
<div class="pick_col color_bucket" id="expand_hover_background"></div>
<div class="tab_col pick_col font_color" id="tab_selected_active_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_selected_active_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_selected_active_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_selected_active_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_selected_active_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_selected_active_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_selected_active_hover_border"></div>
</div>
<div id="t5" class="tab_color_options_row">
<div class="pick_col color_bucket" id="expand_open_background"></div>
<div class="tab_col pick_col font_color" id="tab_discarded_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_discarded_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_discarded_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_discarded_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_discarded_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_discarded_background"></div>
<div class="tab_col pick_col color_border" id="tab_discarded_border"></div>
</div>
<div id="t17" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_discarded_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_discarded_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_discarded_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_discarded_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_discarded_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_discarded_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_discarded_hover_border"></div>
</div>
<div id="t19" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_selected_discarded_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_selected_discarded_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_selected_discarded_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_selected_discarded_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_selected_discarded_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_selected_discarded_background"></div>
<div class="tab_col pick_col color_border" id="tab_selected_discarded_border"></div>
<div class="pick_col color_bucket" id="drag_indicator"></div>
</div>
<div id="t20" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_selected_discarded_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_selected_discarded_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_selected_discarded_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_selected_discarded_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_selected_discarded_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_selected_discarded_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_selected_discarded_hover_border"></div>
</div>
<div id="t6" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_border"></div>
</div>
<div id="t21" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_hover_border"></div>
</div>
<div id="t22" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_active_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_active_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_active_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_active_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_active_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_active_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_active_border"></div>
</div>
<div id="t23" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_active_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_active_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_active_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_active_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_active_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_active_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_active_hover_border"></div>
</div>
<div id="t8" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_border"></div>
</div>
<div id="t18" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_hover_border"></div>
</div>
<div id="t25" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_active_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_active_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_active_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_active_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_active_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_active_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_active_border"></div>
</div>
<div id="t26" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_active_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_active_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_active_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_active_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_active_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_active_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_active_hover_border"></div>
</div>
<div id="t30" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_highlighted_search_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_highlighted_search_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_highlighted_search_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_highlighted_search_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_highlighted_search_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_highlighted_search_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_highlighted_search_border"></div>
</div>
<div id="t31" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_highlighted_search_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_highlighted_search_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_highlighted_search_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_highlighted_search_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_highlighted_search_hover_border"></div>
</div>
<div id="t32" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_active_highlighted_search_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_active_highlighted_search_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_active_highlighted_search_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_active_highlighted_search_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_active_highlighted_search_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_active_highlighted_search_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_active_highlighted_search_border"></div>
</div>
<div id="t33" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_active_highlighted_search_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_active_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_active_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_active_highlighted_search_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_active_highlighted_search_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_active_highlighted_search_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_active_highlighted_search_hover_border"></div>
</div>
<div id="t34" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_highlighted_search_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_highlighted_search_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_highlighted_search_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_highlighted_search_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_highlighted_search_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_highlighted_search_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_highlighted_search_border"></div>
</div>
<div id="t35" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_highlighted_search_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_highlighted_search_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_highlighted_search_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_highlighted_search_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_highlighted_search_hover_border"></div>
</div>
<div id="t36" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_active_highlighted_search_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_active_highlighted_search_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_active_highlighted_search_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_active_highlighted_search_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_active_highlighted_search_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_active_highlighted_search_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_active_highlighted_search_border"></div>
</div>
<div id="t37" class="tab_color_options_row">
<div class="tab_col pick_col font_color" id="tab_filtered_selected_active_highlighted_search_hover_title_font_color"></div>
<div class="tab_col font_weight_normal" id="tab_filtered_selected_active_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_weight_bold" id="tab_filtered_selected_active_highlighted_search_hover_title_font_weight"></div>
<div class="tab_col font_style_normal" id="tab_filtered_selected_active_highlighted_search_hover_title_font_style"></div>
<div class="tab_col font_style_italic" id="tab_filtered_selected_active_highlighted_search_hover_title_font_style"></div>
<div class="tab_col pick_col color_bucket" id="tab_filtered_selected_active_highlighted_search_hover_background"></div>
<div class="tab_col pick_col color_border" id="tab_filtered_selected_active_highlighted_search_hover_border"></div>
</div>
</div>
<div id="scrollbar_size_indicator">
<div class="options_button_minus" id="options_tab_list_scrollbar_width_down"></div>
<div class="options_button_plus" id="options_tab_list_scrollbar_width_up"></div>
<div class="options_button_minus" id="options_tab_list_scrollbar_height_down"></div>
<div class="options_button_plus" id="options_tab_list_scrollbar_height_up"></div>
</div>
<div class="pick_col color_bucket" id="scrollbar_thumb"></div>
<div class="pick_col color_bucket pick_col_hover" id="scrollbar_thumb_hover"></div>
<div class="pick_col color_bucket" id="scrollbar_track"></div>
<div class="pin_list" id="pin_list"></div>
<div id="groups">
<div class="group" id="tab_list">
<div class="children" id="°tab_list"></div>
</div>
</div>
<div id="pin_list_scrollbar"><div id="pin_list_scrollbar_thumb"></div></div>
<div id="group_scrollbar"><div id="group_scrollbar_thumb"></div></div>
<div class="pick_col color_bucket" id="group_list_background"></div>
<div class="pick_col color_border" id="group_list_borders"></div>
<div class="pick_col color_bucket pick_col_hover" id="group_list_button_hover_background"></div>
<div class="pick_col font_color" id="group_list_default_font_color"></div>
<div id="toolbar_groups_block">
<div class="scroll_group" id="scroll_group_up"></div>
<div class="group_list" id="group_list"></div>
<div class="scroll_group" id="scroll_group_down"></div>
</div>
<div id="options_tabs_margins_indicator">
<form action="" id="tabs_margin_spacing" style="position:absolute; left:4px; top:12px;">
<input type="radio" class="tabs_margin_spacing" id="options_tabs_margin_overlap" name="tabs_margin_spacing" value="overlap"/>
<input type="radio" class="tabs_margin_spacing" id="options_tabs_margin_0" name="tabs_margin_spacing" value="no_space"/>
<input type="radio" class="tabs_margin_spacing" id="options_tabs_margin_1" name="tabs_margin_spacing" value="1px_space"/>
</form>
</div>
<div id="options_tabs_indentation_indicator">
<div class="options_button_minus" id="options_tabs_indentation_down"></div>
<div class="options_button_plus" id="options_tabs_indentation_up"></div>
</div>
<div id="options_tabs_roundness_indicator">
<div class="options_button_minus" id="options_tabs_roundness_down"></div>
<div class="options_button_plus" id="options_tabs_roundness_up"></div>
</div>
<div id="options_tabs_size_indicator">
<div class="options_button_minus" id="options_tabs_size_down"></div>
<div class="options_button_plus" id="options_tabs_size_up"></div>
</div>
<div id="pin_list_options_block">
<div class="pick_col color_bucket" id="attention_background"></div>
<div class="pick_col color_border" id="attention_border"></div>
<div class="pick_col color_border" id="pin_list_border_bottom"></div>
<div class="pick_col color_bucket" id="pin_list_background"></div>
</div>
<div class="pick_col color_bucket" id="tab_list_background"></div>
</fieldset>
<fieldset class="field" style="width:816px;">
<legend class="label" id="options_menu"></legend>
<div id="menu_options_block" style="position:relative; top:0px; left:10px;">
<div class="pick_col color_border" id="tabs_menu_border"></div>
<div class="pick_col color_bucket" id="tabs_menu_background"></div>
<div class="pick_col font_color" id="tabs_menu_font"></div>
<div class="pick_col color_border" id="tabs_menu_hover_border"></div>
<div class="pick_col color_bucket" id="tabs_menu_hover_background"></div>
<div class="pick_col color_border" id="tabs_menu_separator"></div>
</div>
<ul class="menu" id="tabs_menu" style="display:inline-block;position:relative;top:0px;left:10px;">
<li class="menu_item" id="menu_hover_sample"></li>
<div class="separator" id="menu_separator1"></div>
<li class="menu_item" id="menu_sample1"></li>
<div class="separator" id="menu_separator2"></div>
<li class="menu_item" id="menu_sample2"></li>
</ul>
</fieldset>
</fieldset>
<fieldset class="field">
<legend class="label" id="options_development"></legend>
<table style="display:inline-block;">
<tr>
<td><input type="checkbox" class="opt_checkbox bg_opt" id="debug"/>
</td>
<td style="position:relative;left:2px;width:3px;">-</td>
<td class="label" id="options_debug"></td>
</tr>
</table>
<br>
<button class="set_button" type="button" id="options_export_debug" style="position: relative; margin:10px;"></button>
<button class="set_button" type="button" id="options_print_debug" style="position: relative; margin:10px;"></button>
<br>
<a href="../translator/translator.html">Your language is not available? Can you help? Translate here.</a>
<br>
<a href="https://drive.google.com/drive/u/1/folders/0B3jXQpRtOfvSelFrTEVHZEx3Nms">Themes</a>
<br>
<a href="https://forum.vivaldi.net/topic/15332/tree-tabs">Forum</a>
<br>
<a href="mailto:karol@jagiello.it">Support Email</a>
<br>
<a href="https://gitlab.com/kroppy/TreeTabs/issues">Report a bug</a>
</fieldset>
<button class="set_button" type="button" id="options_clear_data" style="margin:10px;"></button>
<input type="color" id="color_picker" style="position:absolute; left:-1000px; top:-1000px; width:1px; height:1px; overflow:hidden;">
<div id="DragImage" style="display: none; width:0px; height:0px;"></div>
<script type="text/javascript" src="../global.js"></script>
<script type="text/javascript" src="../scripts/utils.js"></script>
<script type="text/javascript" src="../scripts/dom.js"></script>
<script type="text/javascript" src="../scripts/tabs.js"></script>
<script type="text/javascript" src="../scripts/folders.js"></script>
<script type="text/javascript" src="../scripts/groups.js"></script>
<script type="text/javascript" src="../scripts/menu.js"></script>
<script type="text/javascript" src="../scripts/manager.js"></script>
<script type="text/javascript" src="../scripts/toolbar.js"></script>
<script type="text/javascript" src="../scripts/theme.js"></script>
<script type="text/javascript" src="../scripts/file.js"></script>
<script type="text/javascript" src="../scripts/preferences.js"></script>
<script type="text/javascript" src="../scripts/bookmark.js"></script>
<script type="text/javascript" src="./options.js"></script>
<div id="donate"></div>
<div id="donate_paypal" class="donation_button"></div>
<div id="donate_litecoin" class="donation_button"></div>
<div id="donate_bitcoin" class="donation_button"></div>
<div id="donate_ethereum" class="donation_button"></div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -1,131 +0,0 @@
// 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/
function AppendSampleTabs() {
// folders
AddNewFolder({folderId: "f_folder1", ParentId: "cftab_list", Name: labels.noname_group, Index: 0, ExpandState: "o", AdditionalClass: "o"});
AddNewFolder({folderId: "f_folder2", ParentId: "f_folder1", Name: labels.noname_group, Index: 0, ExpandState: "c", AdditionalClass: "c"});
AddNewFolder({folderId: "f_folder3", ParentId: "f_folder1", Name: labels.noname_group, Index: 0, ExpandState: "c", AdditionalClass: "c"});
// pins
AppendTab({tab: {id: 0, pinned: true, active: false}, Append: true, SkipSetActive: true, SkipSetEvents: true});
AppendTab({tab: {id: 1, pinned: true, active: false}, Append: true, SkipSetActive: true, SkipSetEvents: true});
AppendTab({tab: {id: 10, pinned: true, active: false}, Append: true, SkipSetActive: true, SkipSetEvents: true});
document.getElementById("10").classList.add("attention");
// regular tabs
AppendTab({tab: {id: 2, pinned: false, active: false}, Append: true, SkipSetActive: true, SkipSetEvents: true, addCounter: true});
document.getElementById("tab_title2").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_normal");
AppendTab({tab: {id: 11, pinned: false, active: false}, ParentId: "2", Append: true, SkipSetActive: true, SkipSetEvents: true});
document.getElementById("tab_title11").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_normal_hover");
document.getElementById("tab_header11").classList.add("tab_header_hover");
document.getElementById("tab_header11").classList.add("close_show");
AppendTab({tab: {id: 12, pinned: false, active: false}, ParentId: "2", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "selected_tab"});
document.getElementById("tab_title12").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_normal_selected");
AppendTab({tab: {id: 13, pinned: false, active: false}, ParentId: "2", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "selected_tab"});
document.getElementById("tab_title13").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_normal_selected_hover");
document.getElementById("tab_header13").classList.add("tab_header_hover")
document.getElementById("tab_header13").classList.add("close_show");
document.getElementById("close13").classList.add("close_hover");
// regular active tabs
AppendTab({tab: {id: 3, pinned: false, active: false}, ParentId: "2", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "active_tab"});
document.getElementById("tab_title3").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_active");
AppendTab({tab: {id: 15, pinned: false, active: false}, ParentId: "2", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "active_tab"});
document.getElementById("tab_title15").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_active_hover");
document.getElementById("tab_header15").classList.add("tab_header_hover");
AppendTab({tab: {id: 14, pinned: false, active: false}, ParentId: "2", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "c selected_tab active_tab"});
document.getElementById("tab_title14").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_active_selected");
AppendTab({tab: {id: 16, pinned: false, active: false}, ParentId: "2", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "c selected_tab active_tab"});
document.getElementById("tab_title16").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_active_selected_hover");
document.getElementById("tab_header16").classList.add("tab_header_hover");
document.getElementById("exp16").classList.add("hover");
// discarded tabs
AppendTab({tab: {id: 5, pinned: false, active: false, discarded: true}, Append: true, SkipSetActive: true, SkipSetEvents: true});
document.getElementById("tab_title5").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_discarded");
AppendTab({tab: {id: 17, pinned: false, active: false, discarded: true}, ParentId: "5", Append: true, SkipSetActive: true, SkipSetEvents: true});
document.getElementById("tab_title17").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_discarded_hover");
document.getElementById("tab_header17").classList.add("tab_header_hover");
AppendTab({tab: {id: 19, pinned: false, active: false, discarded: true}, ParentId: "5", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "selected_tab highlighted_drop_target after"});
document.getElementById("tab_title19").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_discarded_selected");
AppendTab({tab: {id: 20, pinned: false, active: false, discarded: true}, ParentId: "5", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "selected_tab"});
document.getElementById("tab_title20").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_discarded_selected_hover");
document.getElementById("tab_header20").classList.add("tab_header_hover");
// search result
AppendTab({tab: {id: 6, pinned: false, active: false}, Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "filtered"});
document.getElementById("tab_title6").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result");
AppendTab({tab: {id: 21, pinned: false, active: false}, ParentId: "6", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "filtered"});
document.getElementById("tab_title21").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result_hover");
document.getElementById("tab_header21").classList.add("tab_header_hover");
AppendTab({tab: {id: 22, pinned: false, active: false}, ParentId: "6", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "filtered active_tab"});
document.getElementById("tab_title22").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result_active");
AppendTab({tab: {id: 23, pinned: false, active: false}, ParentId: "6", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "filtered active_tab"});
document.getElementById("tab_title23").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result_active_hover");
document.getElementById("tab_header23").classList.add("tab_header_hover");
// search result selected
AppendTab({tab: {id: 8, pinned: false, active: false}, ParentId: "6", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "selected_tab filtered"});
document.getElementById("tab_title8").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result_selected");
AppendTab({tab: {id: 18, pinned: false, active: false}, ParentId: "6", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "selected_tab filtered"});
document.getElementById("tab_title18").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result_selected_hover");
document.getElementById("tab_header18").classList.add("tab_header_hover");
AppendTab({tab: {id: 25, pinned: false, active: false}, ParentId: "6", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "selected_tab filtered active_tab"});
document.getElementById("tab_title25").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result_selected_active");
AppendTab({tab: {id: 26, pinned: false, active: false}, ParentId: "6", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "selected_tab filtered active_tab"});
document.getElementById("tab_title26").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result_selected_active_hover");
document.getElementById("tab_header26").classList.add("tab_header_hover");
// search result highlighted
AppendTab({tab: {id: 30, pinned: false, active: false}, Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "filtered highlighted_search"});
document.getElementById("tab_title30").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result_highlighted");
AppendTab({tab: {id: 31, pinned: false, active: false}, ParentId: "30", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "filtered highlighted_search"});
document.getElementById("tab_title31").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result_highlighted_hover");
document.getElementById("tab_header31").classList.add("tab_header_hover");
AppendTab({tab: {id: 32, pinned: false, active: false}, ParentId: "30", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "filtered highlighted_search active_tab"});
document.getElementById("tab_title32").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result_highlighted_active");
AppendTab({tab: {id: 33, pinned: false, active: false}, ParentId: "30", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "filtered highlighted_search active_tab"});
document.getElementById("tab_title33").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result_highlighted_active_hover");
document.getElementById("tab_header33").classList.add("tab_header_hover");
AppendTab({tab: {id: 34, pinned: false, active: false}, ParentId: "30", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "selected_tab filtered highlighted_search"});
document.getElementById("tab_title34").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result_highlighted_selected");
AppendTab({tab: {id: 35, pinned: false, active: false}, ParentId: "30", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "selected_tab filtered highlighted_search"});
document.getElementById("tab_title35").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result_highlighted_selected_hover");
document.getElementById("tab_header35").classList.add("tab_header_hover");
AppendTab({tab: {id: 36, pinned: false, active: false}, ParentId: "30", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "selected_tab filtered highlighted_search active_tab"});
document.getElementById("tab_title36").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result_highlighted_selected_active");
AppendTab({tab: {id: 37, pinned: false, active: false}, ParentId: "30", Append: true, SkipSetActive: true, SkipSetEvents: true, AdditionalClass: "selected_tab filtered highlighted_search active_tab"});
document.getElementById("tab_title37").textContent = chrome.i18n.getMessage("options_theme_tabs_sample_text_search_result_highlighted_selected_active_hover");
document.getElementById("tab_header37").classList.add("tab_header_hover");
document.getElementById("_tab_list").classList.add("active_group");
}

View File

@ -1,580 +0,0 @@
// 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/
function ExportGroup(groupId, filename, save_to_manager) {
let GroupToSave = { group: tt.groups[groupId], folders: {}, tabs: [] };
document.querySelectorAll("#" + groupId + " .folder").forEach(function(s) {
if (tt.folders[s.id]) {
GroupToSave.folders[s.id] = tt.folders[s.id];
}
});
let Tabs = document.querySelectorAll("#" + groupId + " .tab");
if (Tabs.length > 0) {
let lastId = parseInt(Tabs[Tabs.length - 1].id);
Tabs.forEach(function(s) {
chrome.tabs.get(parseInt(s.id), function(tab) {
if ((tab.url).startsWith("www") || (tab.url).startsWith("http") || (tab.url).startsWith("ftp")) {
(GroupToSave.tabs).push({
id: tab.id,
parent: s.parentNode.parentNode.id,
index: Array.from(s.parentNode.children).indexOf(s),
expand: (s.classList.contains("c") ? "c" : (s.classList.contains("o") ? "o" : "")),
url: tab.url
});
}
if (tab.id == lastId) {
if (filename) {
SaveFile(filename, "tt_group", GroupToSave);
}
if (save_to_manager) {
AddGroupToStorage(GroupToSave, true);
}
if (opt.debug) {
log("f: ExportGroup, filename: "+filename+", groupId: "+groupId+", save_to_manager: "+save_to_manager);
}
}
});
});
} else {
if (filename) {
SaveFile(filename, "tt_group", GroupToSave);
}
if (save_to_manager) {
AddGroupToStorage(GroupToSave, true);
}
if (opt.debug) {
log("f: ExportGroup, filename: "+filename+", groupId: "+groupId+", save_to_manager: "+save_to_manager);
}
}
}
function ImportGroup(recreate_group, save_to_manager) {
let file = document.getElementById("file_import");
let fr = new FileReader();
if (file.files[0] == undefined) return;
fr.readAsText(file.files[0]);
fr.onload = function() {
let data = fr.result;
let group = JSON.parse(data);
file.parentNode.removeChild(file);
if (recreate_group) {
RecreateGroup(group);
}
if (save_to_manager) {
AddGroupToStorage(group, true);
}
if (opt.debug) {
log("f: ImportGroup, recreate_group: "+recreate_group+", save_to_manager: "+save_to_manager);
}
}
}
function AddGroupToStorage(group, add_to_manager) {
chrome.storage.local.get(null, function(storage) {
if (storage["hibernated_groups"] == undefined) {
let hibernated_groups = [];
hibernated_groups.push(group);
chrome.storage.local.set({ hibernated_groups: hibernated_groups });
if (add_to_manager) {
AddGroupToManagerList(group);
}
} else {
let hibernated_groups = storage["hibernated_groups"];
hibernated_groups.push(group);
chrome.storage.local.set({ hibernated_groups: hibernated_groups });
if (add_to_manager) {
AddGroupToManagerList(group);
}
}
if (opt.debug) {
log("f: AddGroupToStorage, add_to_manager: "+add_to_manager);
}
});
}
function RecreateGroup(LoadedGroup) {
let NewFolders = {};
let RefsTabs = {};
let NewTabs = [];
let NewGroupId = AddNewGroup(LoadedGroup.group.name, LoadedGroup.group.font);
SetActiveGroup(NewGroupId, false, false);
for (var folder in LoadedGroup.folders) {
let newId = GenerateNewFolderID();
NewFolders[folder] = { id: newId, parent: NewGroupId, index: (LoadedGroup.folders[folder].index), name: (LoadedGroup.folders[folder].name), expand: (LoadedGroup.folders[folder].expand) };
}
for (var folder in NewFolders) {
if (NewFolders[LoadedGroup.folders[folder].parent]) {
NewFolders[folder].parent = NewFolders[LoadedGroup.folders[folder].parent].id;
}
}
(LoadedGroup.tabs).forEach(function(Tab) {
chrome.tabs.create({ url: Tab.url, active: false }, function(new_tab) {
if (new_tab) {
RefsTabs[Tab.id] = new_tab.id;
Tab.id = new_tab.id;
NewTabs.push(Tab);
setTimeout(function() {
let nt = document.getElementById(new_tab.id);
let NewGroupTabs = document.getElementById("ct" + NewGroupId);
if (nt != null && NewGroupTabs != null) {
NewGroupTabs.appendChild(nt);
}
}, 1000);
if (browserId != "O") {
chrome.runtime.sendMessage({command: "discard_tab", tabId: new_tab.id});
}
}
if (NewTabs.length == LoadedGroup.tabs.length - 1) {
setTimeout(function() {
NewTabs.forEach(function(LTab) {
if (LTab.parent == LoadedGroup.group.id) {
LTab.parent = NewGroupId;
}
if (NewFolders[LTab.parent]) {
LTab.parent = NewFolders[LTab.parent].id;
}
if (RefsTabs[LTab.parent]) {
LTab.parent = RefsTabs[LTab.parent];
}
});
setTimeout(function() {
RcreateTreeStructure({}, NewFolders, NewTabs);
}, 1000);
setTimeout(function() {
RcreateTreeStructure({}, NewFolders, NewTabs);
}, 2000);
setTimeout(function() {
RcreateTreeStructure({}, NewFolders, NewTabs);
}, 5000);
}, 2000);
}
});
});
if (opt.debug) {
log("f: RecreateGroup");
}
}
function ExportSession(name, save_to_file, save_to_manager, save_to_autosave_manager) {
chrome.windows.getAll({ windowTypes: ['normal'], populate: true }, function(win) {
chrome.runtime.sendMessage({ command: "get_browser_tabs" }, function(t) {
let tabs = Object.assign({}, t);
chrome.runtime.sendMessage({ command: "get_windows" }, function(w) {
let windows = Object.assign({}, w);
let warn = true;
let ExportWindows = [];
win.forEach(function(CWin) {
if (CWin.tabs.length > 0) {
windows[CWin.id]["id"] = CWin.id;
windows[CWin.id]["tabs"] = [];
CWin.tabs.forEach(function(CTab) {
if ((CTab.url).startsWith("www") || (CTab.url).startsWith("http") || (CTab.url).startsWith("ftp")) {
windows[CWin.id]["tabs"].push({ id: CTab.id, url: CTab.url, parent: tabs[CTab.id].parent, index: tabs[CTab.id].index, expand: tabs[CTab.id].expand });
}
});
ExportWindows.push(windows[CWin.id]);
}
});
if (save_to_file) {
SaveFile(name, "tt_session", ExportWindows);
}
if (save_to_manager) {
AddSessionToStorage(ExportWindows, name, true);
}
if (save_to_autosave_manager) {
AddAutosaveSessionToStorage(ExportWindows, name)
}
if (opt.debug) {
log("f: ExportSession, name: "+name+", save_to_file: "+save_to_file+", save_to_manager: "+save_to_manager+", save_to_autosave_manager: "+save_to_autosave_manager);
}
});
});
});
}
function ImportSession(recreate_session, save_to_manager, merge_session) {
let file = document.getElementById("file_import");
let fr = new FileReader();
if (file.files[0] == undefined) return;
fr.readAsText(file.files[file.files.length - 1]);
fr.onload = function() {
let data = fr.result;
file.parentNode.removeChild(file);
let LoadedSession = JSON.parse(data);
if (opt.debug) {
log("f: ImportSession, recreate_session: "+recreate_session+", merge_session: "+merge_session);
}
if (recreate_session) {
RecreateSession(LoadedSession);
}
if (merge_session) {
ImportMergeTabs(LoadedSession);
}
if (save_to_manager) {
AddSessionToStorage(LoadedSession, (file.files[file.files.length - 1].name).replace(".tt_session", ""), true);
}
}
}
function AddSessionToStorage(session, name, add_to_manager) {
chrome.storage.local.get(null, function(storage) {
if (storage.saved_sessions == undefined) {
let saved_sessions = [];
saved_sessions.push({ name: name, session: session });
chrome.storage.local.set({ saved_sessions: saved_sessions });
if (add_to_manager) {
AddSessionToManagerList(saved_sessions[saved_sessions.length - 1]);
}
} else {
let saved_sessions = storage.saved_sessions;
saved_sessions.push({ name: name, session: session });
chrome.storage.local.set({ saved_sessions: saved_sessions });
if (add_to_manager) {
AddSessionToManagerList(saved_sessions[saved_sessions.length - 1]);
}
}
if (opt.debug) {
log("f: AddSessionToStorage, name: "+name+", add_to_manager: "+add_to_manager);
}
});
}
function AddAutosaveSessionToStorage(session, name) {
chrome.storage.local.get(null, function(storage) {
if (storage.saved_sessions_automatic == undefined) {
let s = [];
s.push({ name: name, session: session });
chrome.storage.local.set({ saved_sessions_automatic: s });
} else {
let s = storage.saved_sessions_automatic;
s.unshift({ name: name, session: session });
if (s[opt.autosave_max_to_keep]) {
s.splice(opt.autosave_max_to_keep, (s.length - opt.autosave_max_to_keep));
}
chrome.storage.local.set({ saved_sessions_automatic: s });
}
if (opt.debug) {
log("f: AddAutosaveSessionToStorage, name: "+name);
}
});
}
function RecreateSession(LoadedSession) {
let RefsTabs = {};
if (opt.debug) {
log("f: RecreateSession");
}
LoadedSession.forEach(function(LWin) {
let NewTabs = [];
let urls = [];
(LWin.tabs).forEach(function(Tab) {
urls.push(Tab.url);
NewTabs.push(Tab);
});
chrome.windows.create({ url: urls /* , discarded: true */ }, function(new_window) {
chrome.runtime.sendMessage({command: "save_groups", windowId: new_window.id, groups: LWin.groups});
chrome.runtime.sendMessage({command: "save_folders", windowId: new_window.id, folders: LWin.folders});
for (let tInd = 0; tInd < new_window.tabs.length; tInd++) {
RefsTabs[NewTabs[tInd].id] = new_window.tabs[tInd].id;
NewTabs[tInd].id = new_window.tabs[tInd].id;
}
for (let tInd = 0; tInd < new_window.tabs.length; tInd++) {
if (RefsTabs[NewTabs[tInd].parent] != undefined) {
NewTabs[tInd].parent = RefsTabs[NewTabs[tInd].parent];
}
}
for (let tInd = 0; tInd < new_window.tabs.length; tInd++) {
if (NewTabs[tInd].parent == "pin_list") {
chrome.tabs.update(new_window.tabs[tInd].id, { pinned: true });
}
chrome.runtime.sendMessage({command: "update_tab", tabId: new_window.tabs[tInd].id, tab: {index: NewTabs[tInd].index, expand: NewTabs[tInd].expand, parent: NewTabs[tInd].parent}});
// if (browserId != "O") {
// chrome.runtime.sendMessage({command: "discard_tab", tabId: new_window.tabs[tInd].id});
// }
}
if (browserId != "O") {
setTimeout(function() {
chrome.runtime.sendMessage({command: "discard_window", windowId: new_window.id});
}, urls.length * 300);
}
});
});
}
// groups and folders are in object, just like tt.groups and tt.folders, but tabs are in array of treetabs objects
function RcreateTreeStructure(groups, folders, tabs) {
if (opt.debug) {
log("f: RcreateTreeStructure");
}
ShowStatusBar({show: true, spinner: true, message: "Quick check and recreating structure..."});
if (groups && Object.keys(groups).length > 0) {
for (var group in groups) {
tt.groups[groups[group].id] = Object.assign({}, groups[group]);
}
AppendGroups(tt.groups);
}
if (folders && Object.keys(folders).length > 0) {
for (var folder in folders) {
tt.folders[folders[folder].id] = Object.assign({}, folders[folder]);
}
AppendFolders(tt.folders);
}
let bgtabs = {};
tabs.forEach(function(Tab) {
if (Tab.parent == "pin_list") {
chrome.tabs.update(Tab.id, { pinned: true });
}
if (Tab.parent != "") {
let tb = document.getElementById(Tab.id);
let tbp = document.getElementById("ct" + Tab.parent);
if (tb && tbp) {
tbp.appendChild(tb);
if (Tab.expand != "") {
tb.classList.add(Tab.expand);
}
}
bgtabs[Tab.id] = { index: Tab.index, parent: Tab.parent, expand: Tab.expand };
}
});
RearrangeTreeTabs(bgtabs, false);
RearrangeFolders(true);
UpdateBgGroupsOrder();
setTimeout(function() {
RefreshExpandStates();
RefreshCounters();
tt.schedule_update_data++;
SaveFolders();
}, 3000);
// ShowStatusBar({show: true, spinner: true, message: "Sorting"});
// ShowStatusBar(false, "Wait just a little more...");
}
function ImportMergeTabs(LoadedSession) {
if (opt.debug) {
log("f: ImportMergeTabs");
}
let RefsWins = {};
let RefsTabs = {};
for (let LWI = 0; LWI < LoadedSession.length; LWI++) { // clear previous window ids
LoadedSession[LWI].id = "";
}
ShowStatusBar({show: true, spinner: true, message: "Loaded Tree structure..."});
chrome.windows.getAll({ windowTypes: ['normal'], populate: true }, function(cw) {
for (let CWI = 0; CWI < cw.length; CWI++) { // Current Windows
for (let LWI = 0; LWI < LoadedSession.length; LWI++) { // Loaded Windows
if (LoadedSession[LWI].id == "") {
let tabsMatch = 0;
for (let CTI = 0; CTI < cw[CWI].tabs.length; CTI++) { // loop Tabs of CWI Window
for (let LTI = 0; LTI < LoadedSession[LWI].tabs.length; LTI++) { // loop Tabs of Loaded Window
if (cw[CWI].tabs[CTI].url == LoadedSession[LWI].tabs[LTI].url) {
RefsTabs[LoadedSession[LWI].tabs[LTI].id] = cw[CWI].tabs[CTI].id;
LoadedSession[LWI].tabs[LTI].id = cw[CWI].tabs[CTI].id;
LoadedSession[LWI].tabs[LTI].url = "";
tabsMatch++;
break;
}
}
}
if (opt.debug) {
log("f: ImportMergeTabs, tabsMatch: "+tabsMatch);
}
if (tabsMatch > LoadedSession[LWI].tabs.length * 0.6) {
LoadedSession[LWI].id = cw[CWI].id;
break;
}
}
}
}
LoadedSession.forEach(function(w) {
if (w.id == "") { // missing window, lets make one
if (opt.debug) {
log("f: ImportMergeTabs, missing window");
}
let NewTabs = [];
let urls = [];
(w.tabs).forEach(function(Tab) {
urls.push(Tab.url);
NewTabs.push(Tab);
});
chrome.windows.create({ url: urls }, function(new_window) {
chrome.runtime.sendMessage({command: "save_groups", windowId: new_window.id, groups: w.groups});
chrome.runtime.sendMessage({command: "save_folders", windowId: new_window.id, folders: w.folders});
for (let tInd = 0; tInd < new_window.tabs.length; tInd++) {
if (NewTabs[tInd]) {
RefsTabs[NewTabs[tInd].id] = new_window.tabs[tInd].id;
NewTabs[tInd].id = new_window.tabs[tInd].id;
}
}
for (let tInd = 0; tInd < NewTabs.length; tInd++) {
if (RefsTabs[NewTabs[tInd].parent] != undefined) {
NewTabs[tInd].parent = RefsTabs[NewTabs[tInd].parent];
}
}
for (let tInd = 0; tInd < new_window.tabs.length; tInd++) {
if (NewTabs[tInd].parent == "pin_list") {
chrome.tabs.update(new_window.tabs[tInd].id, { pinned: true });
}
chrome.runtime.sendMessage({command: "update_tab", tabId: new_window.tabs[tInd].id, tab: {index: NewTabs[tInd].index, expand: NewTabs[tInd].expand, parent: NewTabs[tInd].parent}});
}
let done = 3;
var Append = setInterval(function() {
chrome.runtime.sendMessage({command: "remote_update", groups: w.groups, folders: w.folders, tabs: NewTabs, windowId: w.id });
if (done < 0) { clearInterval(Append); }
done--;
}, 2000);
});
} else { // window exists, lets add missing tabs
let NewTabs = [];
let RefsTabs = {};
chrome.runtime.sendMessage({command: "get_folders", windowId: w.id}, function(f) {
chrome.runtime.sendMessage({command: "get_groups", windowId: w.id}, function(g) {
if (Object.keys(w.groups).length > 0) {
for (var group in w.groups) {
if (group != "" && group != "undefined" && w.groups[group] != undefined) {
g[w.groups[group].id] = Object.assign({}, w.groups[group]);
}
}
}
if (Object.keys(w.folders).length > 0) {
for (var folder in w.folders) {
if (folder != "" && folder != "undefined" && w.folders[folder] != undefined) {
w.folders[w.folders[folder].id] = Object.assign({}, w.folders[folder]);
}
}
}
if (Object.keys(g).length > 0) {
for (var groupId in g) {
w.groups[groupId] = Object.assign({}, g[groupId]);
}
}
if (Object.keys(f).length > 0) {
for (var folderId in f) {
w.folders[folderId] = Object.assign({}, f[folderId]);
}
}
chrome.runtime.sendMessage({command: "save_groups", windowId: w.id, groups: g});
chrome.runtime.sendMessage({command: "save_folders", windowId: w.id, folders: f});
chrome.runtime.sendMessage({ command: "remote_update", groups: w.groups, folders: w.folders, tabs: [], windowId: w.id });
if (w.id == tt.CurrentWindowId) {
RcreateTreeStructure(w.groups, w.folders, []);
}
(w.tabs).forEach(function(Tab) {
if (Tab.url != "") { // missing tab, lets make one
chrome.tabs.create({ url: Tab.url, pinned: (Tab.parent == "pin_list" ? true : false), windowId: w.id }, function(tab) {
RefsTabs[Tab.id] = tab.id;
Tab.id = tab.id;
NewTabs.push(Tab);
chrome.runtime.sendMessage({command: "update_tab", tabId: tab.id, tab: {index: Tab.index, expand: Tab.expand, parent: Tab.parent}});
});
} else {
NewTabs.push(Tab);
}
});
setTimeout(function() {
ShowStatusBar({show: true, spinner: true, message: "Finding reference tabs..."});
for (let tInd = 0; tInd < NewTabs.length; tInd++) {
if (RefsTabs[NewTabs[tInd].parent] != undefined) {
NewTabs[tInd].parent = RefsTabs[NewTabs[tInd].parent];
}
}
}, 4000);
setTimeout(function() {
for (let tInd = 0; tInd < NewTabs.length; tInd++) {
chrome.runtime.sendMessage({command: "update_tab", tabId: NewTabs[tInd].id, tab: {index: NewTabs[tInd].index, expand: NewTabs[tInd].expand, parent: NewTabs[tInd].parent}});
}
let done = 10;
var Append = setInterval(function() {
ShowStatusBar({show: true, spinner: true, message: "Finding other windows to add tabs..."});
if (w.id == tt.CurrentWindowId) {
RcreateTreeStructure(w.groups, w.folders, NewTabs);
} else {
chrome.runtime.sendMessage({command: "remote_update", groups: w.groups, folders: w.folders, tabs: NewTabs, windowId: w.id });
}
if (done < 0) {
ShowStatusBar({show: true, spinner: false, message: "All done.", hideTimeout: 2000});
clearInterval(Append);
}
done--;
}, 500);
}, 6000);
});
});
}
});
});
}
function StartAutoSaveSession() {
if (opt.autosave_interval > 0 && opt.autosave_max_to_keep > 0) {
tt.AutoSaveSession = setInterval(function() {
if (opt.debug) {
log("f: AutoSaveSession, loop time is: "+opt.autosave_interval);
}
let d = new Date();
let newName = d.toLocaleString().replace("/", ".").replace("/", ".").replace(":", "").replace(":", "");
ExportSession(newName, false, false, true);
ShowStatusBar({show: true, spinner: false, message: "Autosave: "+newName, hideTimeout: 1500});
if (document.getElementById("manager_window").style.top != "-500px") {
chrome.storage.local.get(null, function(storage) {
ReAddSessionAutomaticToManagerList(storage);
});
}
}, opt.autosave_interval * 60000);
}
}

80
scripts/bookmark.js Normal file
View File

@ -0,0 +1,80 @@
function Bookmark(rootNode) {
let ToolbarId = browserId == "F" ? "toolbar_____" : "1";
chrome.bookmarks.get(ToolbarId, function(list) {
chrome.bookmarks.search("TreeTabs", function(list) {
let TreeTabsId;
for (var elem in list) {
if (list[elem].parentId == ToolbarId) {
TreeTabsId = list[elem].id;
break;
}
}
if (TreeTabsId == undefined) {
chrome.bookmarks.create({parentId: ToolbarId, title: "TreeTabs"}, function(TreeTabsNew) {
TreeTabsId = TreeTabsNew.id;
});
Bookmark(rootNode);
return;
} else {
let Tabs = document.querySelectorAll("#°" + rootNode.id + " .tab");
if (rootNode.classList.contains("tab")) {
if (Tabs.length > 0) {
chrome.tabs.get(parseInt(rootNode.id), function(tab) {
if (tab) {
chrome.bookmarks.create({parentId: TreeTabsId, title: tab.title}, function(root) {
let TabNodes = document.querySelectorAll("[id='" + rootNode.id + "'], [id='" + rootNode.id + "'] .tab");
for (let s of TabNodes) {
chrome.tabs.get(parseInt(s.id), function(tab) {
if (tab) chrome.bookmarks.create({parentId: root.id, title: tab.title, url: tab.url});
});
}
});
}
});
} else {
chrome.tabs.get(parseInt(rootNode.id), function(tab) {
if (tab) chrome.bookmarks.create({parentId: TreeTabsId, title: tab.title, url: tab.url});
});
}
}
if (rootNode.classList.contains("folder") || rootNode.classList.contains("group")) {
let rootName = labels.noname_group;
if (rootNode.classList.contains("folder") && tt.folders[rootNode.id]) rootName = tt.folders[rootNode.id].name;
if (rootNode.classList.contains("group") && tt.groups[rootNode.id]) rootName = tt.groups[rootNode.id].name;
chrome.bookmarks.create({parentId: TreeTabsId, title: rootName}, function(root) {
let Nodes = {};
let folders = document.querySelectorAll("#°" + rootNode.id + " .folder");
for (let f of folders) {
if (tt.folders[f.id]) {
chrome.bookmarks.create({parentId: root.id, title: tt.folders[f.id].name}, function(Bkfolder) {
Nodes[f.id] = {ttid: f.id, id: Bkfolder.id, ttparent: tt.folders[f.id].parent, parent: root.id};
if (Object.keys(Nodes).length == folders.length) {
for (var elem in Nodes) {
if (Nodes[Nodes[elem].ttparent]) Nodes[Nodes[elem].ttid].parent = Nodes[Nodes[elem].ttparent].id;
}
for (var elem in Nodes) {
chrome.bookmarks.move(Nodes[elem].id, {parentId: Nodes[elem].parent}, function(BkFinalfolder) {});
}
}
});
}
}
setTimeout(function() {
let reverse_tabs = Array.from(Tabs).reverse();
for (let t of reverse_tabs) {
chrome.tabs.get(parseInt(t.id), function(tab) {
if (tab) chrome.bookmarks.create({parentId: (Nodes[t.parentNode.parentNode.id] ? Nodes[t.parentNode.parentNode.id].id : root.id), title: tab.title, url: tab.url});
});
}
// Array.from(Tabs).reverse().forEach(function(t) {
// chrome.tabs.get(parseInt(t.id), function(tab) {
// if (tab) chrome.bookmarks.create({parentId: (Nodes[t.parentNode.parentNode.id] ? Nodes[t.parentNode.parentNode.id].id : root.id), title: tab.title, url: tab.url});
// });
// });
}, 3000);
});
}
}
});
});
}

View File

@ -1,130 +0,0 @@
// 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/
// GLOBAL VARIABLES
let browserId = navigator.userAgent.match("Opera|OPR") !== null ? "O" : (navigator.userAgent.match("Vivaldi") !== null ? "V" : (navigator.userAgent.match("Firefox") !== null ? "F" : "C" ))
let opt = {};
let labels = {
clear_filter: chrome.i18n.getMessage("caption_clear_filter"),
loading: chrome.i18n.getMessage("caption_loading"),
searchbox: chrome.i18n.getMessage("caption_searchbox"),
ungrouped_group: chrome.i18n.getMessage("caption_ungrouped_group"),
noname_group: chrome.i18n.getMessage("caption_noname_group")
};
// BACKGROUND VARIABLES
let b = {
debug: [],
running: false,
schedule_save: -999,
windows: {},
tabs: {},
tt_ids: {},
NewTabsQueue: [],
EmptyTabs: [],
newTabUrl: browserId == "F" ? "about:newtab" : "chrome://startpage/"
};
// DEFAULTS NEEDED FOR START AND FOR OPTIONS PAGE
const DefaultToolbar = {
toolbar_main: ["button_new", "button_pin", "button_undo", "button_search", "button_tools", "button_groups", "button_backup", "button_folders"],
toolbar_search: ["button_filter_type", "filter_search_go_prev", "filter_search_go_next"],
toolbar_shelf_tools: (browserId == "F" ? ["button_manager_window", "button_options", "button_unload", "button_detach", "button_reboot"] : ["button_manager_window", "button_options", "button_bookmarks", "button_downloads", "button_history", "button_settings", "button_extensions", "button_unload", "button_detach", "button_reboot"]),
toolbar_shelf_groups: ["button_groups_toolbar_hide", "button_new_group", "button_remove_group", "button_edit_group", "button_import_group", "button_export_group"],
toolbar_shelf_backup: (browserId == "F" ? ["button_import_bak", "button_import_merge_bak", "button_export_bak"] : ["button_import_bak", "button_import_merge_bak", "button_export_bak", "button_load_bak1", "button_load_bak2", "button_load_bak3"]),
toolbar_shelf_folders: ["button_new_folder", "button_remove_folder", "button_edit_folder"]
};
const DefaultTheme = {
ToolbarShow: true,
ColorsSet: {},
TabsSizeSetNumber: 2,
TabsMargins: "2",
theme_name: "untitled",
theme_version: 4
};
const DefaultPreferences = {
hide_other_groups_tabs_firefox: false,
show_toolbar: true,
skip_load: false,
pin_list_multi_row: true,
always_show_close: false,
never_show_close: false,
allow_pin_close: false,
append_child_tab: "bottom",
append_child_tab_after_limit: "after",
append_orphan_tab: "bottom",
after_closing_active_tab: "below_seek_in_parent",
append_tab_from_toolbar: "group_root",
collapse_other_trees: false,
open_tree_on_hover: true,
promote_children: true,
promote_children_in_first_child: true,
max_tree_depth: -1,
max_tree_drag_drop: true,
max_tree_drag_drop_folders: false,
switch_with_scroll: false,
syncro_tabbar_tabs_order: true,
show_counter_groups: true,
show_counter_tabs: true,
show_counter_tabs_hints: true,
groups_toolbar_default: true,
syncro_tabbar_groups_tabs_order: true,
midclick_tab: "close_tab",
dbclick_tab: "new_tab",
dbclick_group: "new_tab",
// dbclick_group_bar: "new_group",
midclick_group: "nothing",
midclick_folder: "nothing",
dbclick_folder: "rename_folder",
debug: false,
orphaned_tabs_to_ungrouped: false,
tab_group_regexes: [],
move_tabs_on_url_change: "never",
autosave_max_to_keep: 5,
autosave_interval: 15
};
// SIDEBAR VARIABLES
// let active_group = "tab_list";
let tt = {
CurrentWindowId: 0,
active_group: "tab_list",
groups: {},
folders: {},
schedule_update_data: 0,
schedule_rearrange_tabs: 0,
DragNodeClass: "",
DragTreeDepth: 0,
DragOverId: "",
menuItemNode: undefined,
SearchIndex: 0,
DragOverTimer: undefined,
AutoSaveSession: undefined
};
// GLOBAL FUNCTIONS
function GenerateRandomID(){
let letters = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","K","L","M","N","O","P","R","S","T","Q","U","V","W","Y","Z","a","b","c","d","e","f","g","h","i","k","l","m","n","o","p","r","s","t","q","u","v","w","y","z"];
let random = ""; for (let letter = 0; letter < 6; letter++ ) {random += letters[Math.floor(Math.random() * letters.length)];} return random;
}
function GetCurrentPreferences(storage) {
opt = Object.assign({}, DefaultPreferences);
if (storage["preferences"]) {
for (let parameter in storage["preferences"]) {
if (opt[parameter] != undefined) {
opt[parameter] = storage["preferences"][parameter];
// legacy, changed from "after_active" to "after", because it is a parent tab, not necessarily an active tab
if (parameter == "append_child_tab" && storage["preferences"][parameter] == "after_active") {
opt[parameter] = "after";
}
}
}
}
}

720
scripts/dom.js Normal file
View File

@ -0,0 +1,720 @@
function DOM_SetEvents() {
if (opt.debug) Utils_log("f: SetEvents, adding global events.");
let PinList = document.getElementById("pin_list");
if (!opt.switch_with_scroll) {
PinList.onmousewheel = function(event) {
let pinList = document.getElementById("pin_list");
let direction = (event.wheelDelta > 0 || event.detail < 0) ? -1 : 1;
let speed = 0.1;
for (let t = 1; t < 40; t++) {
setTimeout(function() {
if (t < 30) {
speed = speed + 0.1; // accelerate
} else {
speed = speed - 0.3; // decelerate
}
pinList.scrollLeft = pinList.scrollLeft + (direction * speed);
}, t);
}
}
}
window.addEventListener('contextmenu', function(event) {
if (event.target.classList.contains("text_input") == false && opt.debug == false) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
return false;
}
}, false);
document.getElementById("body").addEventListener('contextmenu', function(event) {
if (event.target.classList.contains("text_input") == false && opt.debug == false) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
return false;
}
}, false);
document.body.onresize = function(event) {
DOM_RefreshGUI();
}
document.body.onmousedown = function(event) {
if (event.which == 2) event.preventDefault();
if (event.which == 1 && event.target.classList.contains("menu_item") == false) Menu_HideMenus();
event.stopImmediatePropagation();
if (event.which == 1) DOM_RemoveHeadersHoverClass();
}
document.getElementById("folder_edit_confirm").onmousedown = function(event) {
if (event.which == 1) Folders_FolderRenameConfirm();
}
document.getElementById("folder_edit_discard").onmousedown = function(event) {
if (event.which == 1) DOM_HideRenameDialogs();
}
document.getElementById("group_edit_confirm").onmousedown = function(event) {
if (event.which == 1) Groups_GroupEditConfirm();
}
document.getElementById("group_edit_discard").onmousedown = function(event) {
if (event.which == 1) DOM_HideRenameDialogs();
}
document.getElementById("folder_edit_name").onkeydown = function(event) {
if (event.keyCode == 13) Folders_FolderRenameConfirm();
if (event.which == 27) DOM_HideRenameDialogs();
}
document.getElementById("group_edit_name").onkeydown = function(event) {
if (event.keyCode == 13) Groups_GroupEditConfirm();
if (event.which == 27) DOM_HideRenameDialogs();
}
PinList.onclick = function(event) {
if (event.which == 1 && event.target == this) {
if (opt.pin_list_multi_row || (opt.pin_list_multi_row == false && event.clientY < (this.childNodes[0].getBoundingClientRect().height + this.getBoundingClientRect().top))) DOM_Deselect();
}
}
PinList.onmousedown = function(event) {
if (event.which == 1 && event.target == this) {
if (opt.pin_list_multi_row || (opt.pin_list_multi_row == false && event.clientY < (this.childNodes[0].getBoundingClientRect().height + this.getBoundingClientRect().top))) Menu_HideMenus();
}
if (event.which == 2 && event.target == this) Groups_ActionClickGroup(this, opt.midclick_group);
if (event.which == 3 && event.target == this) Menu_ShowFGlobalMenu(event);
}
PinList.ondragover = function(event) {
if (event.target.id == "pin_list" && tt.DraggingGroup == false && (tt.DraggingPin || tt.DraggingTab || tt.DraggingFolder) && this.classList.contains("highlighted_drop_target") == false) {
DOM_RemoveHighlight();
this.classList.add("highlighted_drop_target");
}
}
PinList.ondblclick = function(event) {
if (event.target == this) Groups_ActionClickGroup(this, opt.dbclick_group);
}
document.getElementById("group_edit_font").onclick = function(event) {
if (event.which == 1) {
event.stopPropagation();
let ColorPicker = document.getElementById("color_picker");
ColorPicker.setAttribute("PickColor", this.id);
ColorPicker.value = "#" + Utils_RGBtoHex(this.style.backgroundColor);
ColorPicker.focus();
ColorPicker.click();
}
}
document.getElementById("color_picker").oninput = function(event) {
document.getElementById(this.getAttribute("PickColor")).style.backgroundColor = this.value;
}
document.getElementById("group_list").ondragleave = function(event) {
if (opt.open_tree_on_hover) {
clearTimeout(tt.DragOverTimer);
tt.DragOverId = "";
}
}
document.body.onkeydown = function(event) {
if (event.ctrlKey && event.which == 65) { // ctrl+a to select all
if (document.querySelector(".pin>.tab_header_hover") != null) {
let query = document.querySelectorAll(".pin");
for (let s of query) {
s.classList.add("selected");
}
}
if (document.querySelectorAll("#" + tt.active_group + " .tab>.tab_header_hover, #" + tt.active_group + " .folder>.folder_header_hover").length > 0) {
let rootId = document.querySelectorAll("#" + tt.active_group + " .tab>.tab_header_hover, #" + tt.active_group + " .folder>.folder_header_hover")[0].parentNode.parentNode.parentNode.id;
let query = document.querySelectorAll("#°" + rootId + ">.folder, #°" + rootId + ">.tab");
for (let s of query) {
s.classList.add("selected");
}
}
}
if (event.ctrlKey && event.which == 73) { // ctrl+i to invert selection
if (document.querySelector(".pin>.tab_header_hover") != null) {
let query = document.querySelectorAll(".pin");
for (let s of query) {
s.classList.toggle("selected");
}
}
if (document.querySelectorAll("#" + tt.active_group + " .tab>.tab_header_hover, #" + tt.active_group + " .folder>.folder_header_hover").length > 0) {
let rootId = document.querySelectorAll("#" + tt.active_group + " .tab>.tab_header_hover, #" + tt.active_group + " .folder>.folder_header_hover")[0].parentNode.parentNode.parentNode.id;
let query = document.querySelectorAll("#°" + rootId + ">.folder, #°" + rootId + ">.tab");
for (let s of query) {
s.classList.toggle("selected");
}
}
}
if (event.which == 27) DOM_Deselect(); // esc to unselect tabs and folders
if (event.altKey && event.which == 71) Groups_GroupsToolbarToggle(); // alt+g to toggle group bar
if (event.which == 192 || event.which == 70) { // new folder
if (tt.pressed_keys.indexOf(event.which) == -1) tt.pressed_keys.push(event.which);
if (tt.pressed_keys.indexOf(192) != -1 && tt.pressed_keys.indexOf(70) != -1) {
let FolderId = Folders_AddNewFolder({});
Folders_ShowRenameFolderDialog(FolderId);
}
}
DOM_RefreshGUI();
}
document.body.onkeyup = function(event) {
if (tt.pressed_keys.indexOf(event.which) != -1) tt.pressed_keys.splice(tt.pressed_keys.indexOf(event.which), 1);
}
document.body.ondragover = function(event) {
if (opt.debug) Utils_log("drag over: " + event.target.id);
event.preventDefault();
}
document.ondrop = function(event) {
if (opt.debug) Utils_log("dropped on window: " + tt.CurrentWindowId);
let Nodes = event.dataTransfer.getData("Nodes") ? JSON.parse(event.dataTransfer.getData("Nodes")) : [];
let NodesTypes = event.dataTransfer.getData("NodesTypes") ? JSON.parse(event.dataTransfer.getData("NodesTypes")) : {DraggingGroup: false, DraggingPin: false, DraggingTab: false, DraggingFolder: false};
let Group = event.dataTransfer.getData("Group") ? JSON.parse(event.dataTransfer.getData("Group")) : {};
let SourceWindowId = event.dataTransfer.getData("SourceWindowId") ? JSON.parse(event.dataTransfer.getData("SourceWindowId")) : 0;
let target = document.querySelector(".highlighted_drop_target");
let where = target ? (target.classList.contains("before") ? "before" : (target.classList.contains("after") ? "after" : "inside")) : "";
let ActiveGroup = document.getElementById(tt.active_group);
let Scroll = ActiveGroup.scrollTop;
clearTimeout(tt.DragOverTimer);
tt.DragOverId = "";
tt.Dragging = false;
chrome.runtime.sendMessage({command: "drag_end"});
event.preventDefault();
if (SourceWindowId == tt.CurrentWindowId) {
DOM_DropToTarget({NodesTypes: NodesTypes, Nodes: Nodes, TargetNode: target, where: where, Group: Group, Scroll: Scroll});
} else {
DOM_FreezeSelection();
if (NodesTypes.DraggingGroup) {
tt.groups[Group.id] = Object.assign({}, Group);
Groups_AppendGroupToList(Group.id, Group.name, Group.font, true);
}
let TabsIds = [];
for (let i = 0; i < Nodes.length; i++) {
if (Nodes[i].NodeClass == "folder") {
Folders_AddNewFolder({folderId: Nodes[i].id, ParentId: Nodes[i].parent, Name: Nodes[i].name, Index: Nodes[i].index, ExpandState: Nodes[i].expand});
chrome.runtime.sendMessage({command: "remove_folder", folderId: Nodes[i].id});
}
if (Nodes[i].NodeClass == "pin") {
chrome.tabs.update(parseInt(Nodes[i].id), {pinned: false});
TabsIds.push(parseInt(Nodes[i].id));
}
if (Nodes[i].NodeClass == "tab") TabsIds.push(parseInt(Nodes[i].id));
}
chrome.tabs.move(TabsIds, {windowId: tt.CurrentWindowId, index: -1}, function(MovedTab) {
let Stop = 500;
let DropNodes = setInterval(function() {
Stop--;
let all_ok = true;
for (let i = 0; i < Nodes.length; i++) {
if (document.getElementById(Nodes[i].id) == null) all_ok = false;
}
DOM_DropToTarget({NodesTypes: NodesTypes, Nodes: Nodes, TargetNode: target, where: where, Group: Group, Scroll: Scroll});
if (NodesTypes.DraggingGroup) chrome.runtime.sendMessage({command: "remove_group", groupId: Group.id});
if (all_ok || Stop < 0) {
setTimeout(function() {
clearInterval(DropNodes);
}, 300);
}
}, 100);
});
}
}
document.ondragleave = function(event) {
if (opt.debug) Utils_log("global dragleave");
DOM_RemoveHighlight();
if (opt.open_tree_on_hover) {
clearTimeout(tt.DragOverTimer);
tt.DragOverId = "";
}
}
document.ondragend = function(event) {
if (opt.debug) Utils_log("drag_end");
let Nodes = event.dataTransfer.getData("Nodes") ? JSON.parse(event.dataTransfer.getData("Nodes")) : [];
let NodesTypes = event.dataTransfer.getData("NodesTypes") ? JSON.parse(event.dataTransfer.getData("NodesTypes")) : {DraggingGroup: false, DraggingPin: false, DraggingTab: false, DraggingFolder: false};
let Group = event.dataTransfer.getData("Group") ? JSON.parse(event.dataTransfer.getData("Group")) : {};
setTimeout(function() {
if (tt.Dragging && ((browserId == "F" && ( event.screenX < event.view.mozInnerScreenX || event.screenX > (event.view.mozInnerScreenX + window.innerWidth) || event.screenY < event.view.mozInnerScreenY || event.screenY > (event.view.mozInnerScreenY + window.innerHeight))) || (browserId != "F" && (event.pageX < 0 || event.pageX > window.outerWidth || event.pageY < 0 || event.pageY > window.outerHeight)))) Tabs_Detach(Nodes, NodesTypes, Group);
DOM_CleanUpDragAndDrop();
tt.Dragging = false;
chrome.runtime.sendMessage({command: "drag_end"});
}, 300);
if (opt.open_tree_on_hover) {
clearTimeout(tt.DragOverTimer);
tt.DragOverId = "";
}
}
}
function DOM_BindTabsSwitchingToMouseWheel(Id) {
if (opt.debug) Utils_log("f: BindTabsSwitchingToMouseWheel, binding tabs switch to group: " + Id);
document.getElementById(Id).onwheel = function(event) {
event.preventDefault();
let prev = event.deltaY < 0;
if (prev) {
Tabs_ActivatePrevTab(true);
} else {
Tabs_ActivateNextTab(true);
}
}
}
function DOM_InsertDropToTarget(p) {
if (p.AppendToTarget) {
for (let i = 0; i < p.Nodes.length; i++) {
let Node = document.getElementById(p.Nodes[i].id);
if (Node != null) {
if (p.Nodes[i].selected) {
DOM_AppendToNode(Node, p.TargetNode);
Node.classList.add("selected");
if (p.Nodes[i].temporary) Node.classList.add("selected_temporarly");
} else {
if (Node.parentNode.id != p.Nodes[i].parent) DOM_AppendToNode(Node, document.getElementById(p.Nodes[i].parent));
}
}
}
}
if (p.BeforeTarget) {
for (i = 0; i < p.Nodes.length; i++) {
let Node = document.getElementById(p.Nodes[i].id);
if (Node != null) {
if (p.Nodes[i].selected) {
DOM_InsterBeforeNode(Node, p.TargetNode);
Node.classList.add("selected");
if (p.Nodes[i].temporary) Node.classList.add("selected_temporarly");
} else {
if (Node.parentNode.id != p.Nodes[i].parent) DOM_AppendToNode(Node, document.getElementById(p.Nodes[i].parent));
}
}
}
}
if (p.AfterTarget) {
let i = p.after ? (p.Nodes.length - 1) : 0;
for (i = p.Nodes.length - 1; i >= 0; i--) {
let Node = document.getElementById(p.Nodes[i].id);
if (Node != null) {
if (p.Nodes[i].selected) {
DOM_InsterAfterNode(Node, p.TargetNode);
Node.classList.add("selected");
if (p.Nodes[i].temporary) Node.classList.add("selected_temporarly");
} else {
if (Node.parentNode.id != p.Nodes[i].parent) DOM_AppendToNode(Node, document.getElementById(p.Nodes[i].parent));
}
}
}
}
}
function DOM_New(type, parent, parameters, style) {
let NewElement = document.createElement(type);
for (param in parameters) {
NewElement[param] = parameters[param];
}
for (param in style) {
NewElement.style[param] = style[param];
}
if (parent) parent.appendChild(NewElement);
return NewElement;
}
async function DOM_SetStyle(node, style) {
for (param in style) {
node.style[param] = style[param];
}
}
function DOM_SetClasses(node, add, remove, toggle) {
let Ind = 0;
for (Ind = 0; Ind < add.length; Ind++) {
node.classList.add(add[Ind]);
}
for (Ind = 0; Ind < remove.length; Ind++) {
node.classList.remove(remove[Ind]);
}
for (Ind = 0; Ind < toggle.length; Ind++) {
node.classList.toggle(toggle[Ind]);
}
}
function DOM_DropToTarget(p) { // Class: ("group", "tab", "folder"), DraggedTabNode: TabId, TargetNode: query node, TabsIdsSelected: arr of selected tabIds, TabsIds: arr of tabIds, TabsIdsParents: arr of parent tabIds, Folders: object with folders objects, FoldersSelected: arr of selected folders ids, Group: groupId, Scroll: bool
if (p.TargetNode != null) {
let pinTabs = false;
if (p.NodesTypes.DraggingPin || p.NodesTypes.DraggingTab || p.NodesTypes.DraggingFolder) {
if (p.TargetNode.classList.contains("pin") || p.TargetNode.classList.contains("tab") || p.TargetNode.classList.contains("folder")) {
if (p.TargetNode.classList.contains("pin")) pinTabs = true;
if (p.where == "inside") DOM_InsertDropToTarget({TargetNode: p.TargetNode.childNodes[1], AppendToTarget: true, Nodes: p.Nodes}); // PINS NEVER HAVE INSIDE, SO WILL BE IGNORED
if (p.where == "before") DOM_InsertDropToTarget({TargetNode: p.TargetNode, BeforeTarget: true, Nodes: p.Nodes});
if (p.where == "after") DOM_InsertDropToTarget({TargetNode: p.TargetNode, AfterTarget: true, Nodes: p.Nodes});
}
if (p.TargetNode.id == "pin_list") {
DOM_InsertDropToTarget({TargetNode: p.TargetNode, AppendToTarget: true, Nodes: p.Nodes});
pinTabs = true;
}
if (p.TargetNode.classList.contains("group")) DOM_InsertDropToTarget({TargetNode: p.TargetNode.childNodes[0], AppendToTarget: true, Nodes: p.Nodes});
if (p.TargetNode.classList.contains("group_button")) {
let group = document.getElementById("°" + p.TargetNode.id.substr(1));
DOM_InsertDropToTarget({TargetNode: group, Nodes: p.Nodes, AppendToTarget: true});
}
setTimeout(function() {Folders_SaveFolders();}, 600);
}
if (p.NodesTypes.DraggingGroup) {
if (p.where == "before") DOM_InsterBeforeNode(document.getElementById("_" + p.Group.id), p.TargetNode);
if (p.where == "after") DOM_InsterAfterNode(document.getElementById("_" + p.Group.id), p.TargetNode);
Groups_UpdateBgGroupsOrder();
Groups_RearrangeGroupsLists();
}
for (i = 0; i < p.Nodes.length; i++) {
if (p.Nodes[i].NodeClass == "pin" || p.Nodes[i].NodeClass == "tab") {
if (tt.tabs[p.Nodes[i].id]) {
if (tt.tabs[p.Nodes[i].id].Node.classList.contains("pin") != pinTabs) {
tt.tabs[p.Nodes[i].id].SetTabClass(pinTabs);
tt.tabs[p.Nodes[i].id].pinned = pinTabs;
chrome.tabs.update(parseInt(p.Nodes[i].id), {pinned: pinTabs});
}
}
}
}
if (opt.syncro_tabbar_tabs_order) {
let tabIds = Array.prototype.map.call(document.querySelectorAll(".pin, .tab"), function(s) {return parseInt(s.id);});
for (i = 0; i < p.Nodes.length; i++) {
if (p.Nodes[i].NodeClass == "pin" || p.Nodes[i].NodeClass == "tab") chrome.tabs.move(parseInt(p.Nodes[i].id), {index: tabIds.indexOf(parseInt(p.Nodes[i].id))});
}
setTimeout(function() {tt.schedule_rearrange_tabs++;}, 500);
}
}
Groups_KeepOnlyOneActiveTabInGroup();
DOM_RefreshExpandStates();
DOM_RefreshCounters();
setTimeout(function() {
DOM_RemoveHighlight();
}, 100);
setTimeout(function() {
if (opt.syncro_tabbar_groups_tabs_order) tt.schedule_rearrange_tabs++;
// DOM_RefreshExpandStates();
// DOM_RefreshCounters();
tt.schedule_update_data++;
DOM_RefreshGUI();
DOM_CleanUpDragAndDrop();
if (opt.debug) Utils_log("DropToTarget END");
}, 500);
}
function DOM_AppendToNode(Node, AppendNode) {
if (Node != null && AppendNode != null) AppendNode.appendChild(Node);
}
function DOM_InsterBeforeNode(Node, BeforeNode) {
if (Node != null && BeforeNode != null) BeforeNode.parentNode.insertBefore(Node, BeforeNode);
}
function DOM_InsterAfterNode(Node, AfterNode) {
if (Node != null && AfterNode != null) {
if (AfterNode.nextSibling != null) {
AfterNode.parentNode.insertBefore(Node, AfterNode.nextSibling);
} else {
AfterNode.parentNode.appendChild(Node);
}
}
}
function DOM_PromoteChildrenToFirstChild(Node) {
let NewParent = Node.childNodes[1].firstChild.childNodes[1];
Node.childNodes[1].parentNode.parentNode.insertBefore(Node.childNodes[1].firstChild, Node.childNodes[1].parentNode);
while (Node.childNodes[1].firstChild) {
NewParent.appendChild(Node.childNodes[1].firstChild);
}
}
function DOM_GetAllParents(Node) {
let Parents = [];
let ParentNode = Node.parentNode;
while (ParentNode.parentNode != null) {
Parents.push(ParentNode.parentNode);
ParentNode = ParentNode.parentNode;
}
return Parents;
}
function DOM_GetParentsByClass(Node, Class) {
let Parents = [];
let ParentNode = Node;
if (ParentNode == null) return Parents;
while (ParentNode.parentNode != null) {
if (ParentNode.parentNode.classList != undefined && ParentNode.parentNode.classList.contains(Class)) Parents.push(ParentNode.parentNode);
ParentNode = ParentNode.parentNode;
}
return Parents;
}
function DOM_GetParentsBy2Classes(Node, ClassA, ClassB) {
let Parents = [];
let ParentNode = Node;
while (ParentNode.parentNode != null) {
if (ParentNode.parentNode.classList != undefined && ParentNode.parentNode.classList.contains(ClassA) && ParentNode.parentNode.classList.contains(ClassB)) Parents.push(ParentNode.parentNode);
ParentNode = ParentNode.parentNode;
}
return Parents;
}
function DOM_HideRenameDialogs() {
let query = document.querySelectorAll(".edit_dialog");
for (let s of query) {
DOM_SetStyle(s, {display: "none", top: "-500px", left: "-500px"});
}
}
function DOM_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")) Folders_SaveFolders();
} else {
if (Node.classList.contains("c")) {
if (opt.collapse_other_trees) {
let thisTreeTabs = DOM_GetParentsByClass(Node.childNodes[0], "tab"); // start from tab's first child, instead of tab, important to include clicked tab as well
let thisTreeFolders = DOM_GetParentsByClass(Node.childNodes[0], "folder");
let query = document.querySelectorAll("#" + tt.active_group + " .o.tab");
for (let s of query) {
DOM_SetClasses(s, ["c"], ["o"], []);
chrome.runtime.sendMessage({command: "update_tab", tabId: parseInt(s.id), tab: {expand: "c"}});
}
query = document.querySelectorAll("#" + tt.active_group + " .o.folder");
for (let s of query) {
DOM_SetClasses(s, ["c"], ["o"], []);
}
for (let s of thisTreeTabs) {
DOM_SetClasses(s, ["o"], ["c"], []);
chrome.runtime.sendMessage({command: "update_tab", tabId: parseInt(s.id), tab: {expand: "o"}});
}
for (let s of thisTreeFolders) {
DOM_SetClasses(s, ["o"], ["c"], []);
}
Folders_SaveFolders();
if (Node.classList.contains("tab") && tt.tabs[Node.id]) tt.tabs[Node.id].ScrollToTab();
} else {
DOM_SetClasses(Node, ["o"], ["c"], []);
if (Node.classList.contains("tab")) chrome.runtime.sendMessage({command: "update_tab", tabId: parseInt(Node.id), tab: {expand: "o"}});
if (Node.classList.contains("folder")) Folders_SaveFolders();
}
}
}
}
function DOM_Select(event, TabNode) {
if (event.shiftKey) { // SET SELECTION WITH SHIFT
let LastSelected = document.querySelector("#" + tt.active_group + " .selected.selected_last");
if (LastSelected == null) LastSelected = document.querySelector(".pin.active_tab, #" + tt.active_group + " .tab.active_tab");
if (LastSelected != null && TabNode.parentNode.id == LastSelected.parentNode.id) {
if (!event.ctrlKey) {
let query = document.querySelectorAll(".pin.selected, #" + tt.active_group + " .selected");
for (let s of query) {
DOM_SetClasses(s, [], ["selected_frozen", "selected_temporarly", "selected", "selected_last"], []);
}
}
let ChildrenArray = Array.from(TabNode.parentNode.children);
let activeTabIndex = ChildrenArray.indexOf(LastSelected);
let thisTabIndex = ChildrenArray.indexOf(TabNode);
let fromIndex = thisTabIndex >= activeTabIndex ? activeTabIndex : thisTabIndex;
let toIndex = thisTabIndex >= activeTabIndex ? thisTabIndex : activeTabIndex;
for (let i = fromIndex; i <= toIndex; i++) {
LastSelected.parentNode.childNodes[i].classList.add("selected");
if (i == toIndex && event.ctrlKey) LastSelected.parentNode.childNodes[i].classList.add("selected_last");
}
}
}
if (event.ctrlKey && !event.shiftKey) { // TOGGLE SELECTION WITH CTRL
TabNode.classList.toggle("selected");
if (TabNode.classList.contains("selected")) {
let query = document.querySelectorAll(".selected_last");
for (let s of query) {
s.classList.remove("selected_last");
}
TabNode.classList.add("selected_last");
} else {
TabNode.classList.remove("selected_last");
}
}
}
function DOM_Deselect() {
let query = document.querySelectorAll("#pin_list .selected");
for (let s of query) {
s.classList.remove("selected");
}
query = document.querySelectorAll("#" + tt.active_group + " .selected");
for (let s of query) {
s.classList.remove("selected");
}
}
function DOM_FreezeSelection(all) {
if (all) {
let query = document.querySelectorAll(".selected");
for (let s of query) {
DOM_SetClasses(s, ["selected_frozen"], ["selected", "selected_last"], []);
}
} else {
let query = document.querySelectorAll(".group:not(#" + tt.active_group + ") .selected");
for (let s of query) {
DOM_SetClasses(s, ["selected_frozen"], ["selected", "selected_last"], []);
}
}
}
function DOM_CleanUpDragAndDrop() {
if (opt.debug) Utils_log("f: CleanUpDragAndDrop, unfreezing and removing temporary classes...");
let query = document.querySelectorAll(".selected_frozen");
for (let s of query) {
DOM_SetClasses(s, ["selected"], ["selected_frozen"], []);
}
query = document.querySelectorAll(".selected_temporarly");
for (let s of query) {
DOM_SetClasses(s, [], ["selected", "selected_frozen"], []);
}
query = document.querySelectorAll(".tab_header_hover");
for (let s of query) {
s.classList.remove("tab_header_hover");
}
query = document.querySelectorAll(".folder_header_hover");
for (let s of query) {
s.classList.remove("folder_header_hover");
}
query = document.querySelectorAll(".dragged_tree");
for (let s of query) {
s.classList.remove("dragged_tree");
}
query = document.querySelectorAll(".dragged_parents");
for (let s of query) {
s.classList.remove("dragged_parents");
}
if (opt.debug) Utils_log("f: removing DraggingParams...");
tt.DragTreeDepth = 0;
tt.DraggingGroup = false;
tt.DraggingTab = false;
tt.DraggingFolder = false;
tt.DraggingPin = false;
tt.DragOverId = "";
}
function DOM_RemoveHighlight() {
let query = document.querySelectorAll(".highlighted_drop_target");
for (let s of query) {
DOM_SetClasses(s, [], ["before", "after", "inside", "highlighted_drop_target"], []);
}
}
function DOM_RemoveHeadersHoverClass() {
let query = document.querySelectorAll(".folder_header_hover, .tab_header_hover");
for (let s of query) {
DOM_SetClasses(s, [], ["folder_header_hover", "tab_header_hover"], []);
}
}
function DOM_Loadi18n() {
let query = document.querySelectorAll(".button, .manager_window_toolbar_button");
for (let s of query) {
s.title = chrome.i18n.getMessage(s.id);
}
query = document.querySelectorAll(".menu_item, .edit_dialog_button, #manager_window_header_title, .manager_window_label");
for (let s of query) {
s.textContent = chrome.i18n.getMessage(s.id);
}
}
async function DOM_RefreshExpandStates() { // refresh open closed trees states
let query = document.querySelectorAll("#" + tt.active_group + " .folder, #" + tt.active_group + " .tab");
for (let s of query) {
if (s.childNodes[1].children.length == 0) {
s.classList.remove("o"); s.classList.remove("c");
} else {
if (s.classList.contains("o") == false && s.classList.contains("c") == false) s.classList.add("o");
}
}
query = document.querySelectorAll(".pin");
for (let s of query) {
s.classList.remove("o"); s.classList.remove("c");
}
}
async function DOM_RefreshCounters() {
if (opt.show_counter_tabs || opt.show_counter_tabs_hints) {
let query = document.querySelectorAll("#" + tt.active_group + " .o.tab, #" + tt.active_group + " .c.tab");
for (let s of query) {
if (opt.show_counter_tabs) s.childNodes[0].childNodes[1].childNodes[0].textContent = document.querySelectorAll("[id='" + s.id + "'] .tab").length;
if (opt.show_counter_tabs_hints) {
let title = s.childNodes[0].getAttribute("tabTitle");
s.childNodes[0].title = (document.querySelectorAll("[id='" + s.id + "'] .tab").length + " • ") + title;
}
}
query = document.querySelectorAll("#" + tt.active_group + " .folder");
for (let s of query) {
if (opt.show_counter_tabs && tt.folders[s.id]) s.childNodes[0].childNodes[1].childNodes[0].textContent = document.querySelectorAll("[id='" + s.id + "'] .tab").length;
if (opt.show_counter_tabs_hints && tt.folders[s.id]) s.childNodes[0].title = (document.querySelectorAll("[id='" + s.id + "'] .tab").length + " • ") + tt.folders[s.id].name;
}
}
}
async function DOM_RefreshGUI() {
let toolbar = document.getElementById("toolbar");
let toolbarHeight = 27;
if (toolbar.children.length > 0) {
DOM_SetStyle(toolbar, {height: "", width: "", display: "", border: "", padding: ""});
if (document.querySelector(".on.button") != null) {
toolbar.style.height = "53px";
toolbarHeight = 54;
} else {
toolbar.style.height = "26px";
}
} else {
DOM_SetStyle(toolbar, {height: "0px", width: "0px", display: "none", border: "none", padding: "0"});
toolbar.style.height = "0px";
toolbarHeight = 0;
}
let group_list = document.getElementById("group_list");
group_list.style.width = document.body.clientWidth + 50 + "px";
let pin_list = document.getElementById("pin_list");
if (pin_list.children.length > 0) {
DOM_SetStyle(pin_list, {top: toolbarHeight + "px", height: "", width: "", display: "", border: "", padding: ""});
} else {
DOM_SetStyle(pin_list, {top: "0px", height: "0px", width: "0px", display: "none", border: "none", padding: "0"});
}
let pin_listHeight = pin_list.getBoundingClientRect().height;
let toolbar_groups = document.getElementById("toolbar_groups");
DOM_SetStyle(toolbar_groups, {top: toolbarHeight + pin_listHeight + "px", height: document.body.clientHeight - toolbarHeight - pin_listHeight + "px"});
let toolbar_groupsWidth = toolbar_groups.getBoundingClientRect().width;
if (opt.show_counter_groups) {
let query = document.querySelectorAll(".group");
for (let s of query) {
let groupLabel = document.getElementById("_gte" + s.id);
if (groupLabel) groupLabel.textContent = (tt.groups[s.id] ? tt.groups[s.id].name : labels.noname_group) + " (" + document.querySelectorAll("#" + s.id + " .tab").length + ")";
}
} else {
let query = document.querySelectorAll(".group");
for (let s of query) {
let groupLabel = document.getElementById("_gte" + s.id);
if (groupLabel) groupLabel.textContent = tt.groups[s.id] ? tt.groups[s.id].name : labels.noname_group;
}
}
let query = document.querySelectorAll(".group_button");
for (let s of query) {
s.style.height = s.firstChild.getBoundingClientRect().height + "px";
}
let groups = document.getElementById("groups");
let groupsHeight = document.body.clientHeight - toolbarHeight - pin_listHeight;
let groupsWidth = document.body.clientWidth - toolbar_groupsWidth - 1;
DOM_SetStyle(groups, {top: toolbarHeight + pin_listHeight + "px", left: toolbar_groupsWidth + "px", height: groupsHeight + "px", width: groupsWidth + "px"});
let PanelList = document.querySelector(".mw_pan_on>.manager_window_list");
let PanelListHeight = 3 + PanelList.children.length * 18;
let ManagerWindowPanelButtons = document.querySelector(".mw_pan_on>.manager_window_panel_buttons");
let ManagerWindowPanelButtonsHeight = ManagerWindowPanelButtons.clientHeight;
let MaxAllowedHeight = document.body.clientHeight - 140;
if (PanelListHeight + ManagerWindowPanelButtonsHeight < MaxAllowedHeight) {
PanelList.style.height = PanelListHeight + "px";
} else {
PanelList.style.height = MaxAllowedHeight - ManagerWindowPanelButtonsHeight + "px";
}
let ManagerWindow = document.getElementById("manager_window");
ManagerWindow.style.height = PanelList.clientHeight + ManagerWindowPanelButtonsHeight + 56 + "px";
}
function DOM_AutoRefreshMediaIcons() { // if changeInfo.audible listener does not work, this is my own implementation, hopefully this will not affect performance too much
setInterval(function() {
chrome.tabs.query({currentWindow: true, audible: true, discarded: false}, function(tabs) {
let query = document.querySelectorAll(".audible, .muted");
for (let s of query) {
s.classList.remove("audible"); s.classList.remove("muted");
}
for (let tab of tabs) {
if (tab.audible) document.getElementById(tab.id).classList.add("audible");
if (tab.mutedInfo.muted) document.getElementById(tab.id).classList.add("muted");
}
});
}, 2000);
}

View File

@ -1,655 +0,0 @@
// 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/
function SetEvents() {
if (opt.debug) {
log("f: SetEvents, adding global events.");
}
let PinList = document.getElementById("pin_list");
if (!opt.switch_with_scroll) {
PinList.onmousewheel = function(event) {
let pinList = document.getElementById("pin_list");
let direction = (event.wheelDelta > 0 || event.detail < 0) ? -1 : 1;
let speed = 0.1;
for (let t = 1; t < 40; t++) {
setTimeout(function() {
if (t < 30) {
speed = speed+0.1; // accelerate
} else {
speed = speed-0.3; // decelerate
}
pinList.scrollLeft = pinList.scrollLeft+(direction*speed);
}, t);
}
}
}
document.oncontextmenu = function (event) {
if (!event.ctrlKey && event.target.classList.contains("text_input") == false) {
event.preventDefault();
event.stopPropagation();
return false;
}
};
window.addEventListener('contextmenu', function (event) {
if (!event.ctrlKey && event.target.classList.contains("text_input") == false) {
event.preventDefault();
event.stopPropagation();
return false;
}
}, false);
document.body.onresize = function(event) {
RefreshGUI();
}
// MOUSE DOWN EVENTS
document.body.onmousedown = function(event) {
if (event.which == 2) {
event.preventDefault();
}
if (event.which == 1 && event.target.classList.contains("menu_item") == false) {
HideMenus();
}
event.stopImmediatePropagation();
if (event.which == 1) {
RemoveHeadersHoverClass();
}
}
// CONFIRM EDIT FOLDER
document.getElementById("folder_edit_confirm").onmousedown = function(event) {
if (event.which == 1) {
FolderRenameConfirm();
}
}
// DISCARD EDIT FOLDER
document.getElementById("folder_edit_discard").onmousedown = function(event) {
if (event.which == 1) {
HideRenameDialogs();
}
}
// CONFIRM EDIT GROUP
document.getElementById("group_edit_confirm").onmousedown = function(event) {
if (event.which == 1) {
GroupEditConfirm();
}
}
// DISCARD EDIT GROUP
document.getElementById("group_edit_discard").onmousedown = function(event) {
if (event.which == 1) {
HideRenameDialogs();
}
}
document.getElementById("folder_edit_name").onkeydown = function(event) {
if (event.keyCode == 13) {
FolderRenameConfirm();
}
if (event.which == 27) {
HideRenameDialogs();
}
}
document.getElementById("group_edit_name").onkeydown = function(event) {
if (event.keyCode == 13) {
GroupEditConfirm();
}
if (event.which == 27) {
HideRenameDialogs();
}
}
PinList.onclick = function(event) {
if (event.which == 1 && event.target == this) {
if (opt.pin_list_multi_row || (opt.pin_list_multi_row == false && event.clientY < (this.childNodes[0].getBoundingClientRect().height + this.getBoundingClientRect().top))) {
DeselectFolders();
DeselectTabs();
}
}
}
PinList.onmousedown = function(event) {
if (event.which == 1 && event.target == this) {
if (opt.pin_list_multi_row || (opt.pin_list_multi_row == false && event.clientY < (this.childNodes[0].getBoundingClientRect().height + this.getBoundingClientRect().top))) {
HideMenus();
}
}
if (event.which == 2 && event.target == this) {
ActionClickGroup(this, opt.midclick_group);
}
if (event.which == 3 && event.target == this) {
ShowFGlobalMenu(event);
}
}
PinList.ondragover = function(event) {
// PIN,TAB==>PINLIST
if (event.target.id == "pin_list" && tt.DragNodeClass == "tab" && this.classList.contains("highlighted_drop_target") == false) {
RemoveHighlight();
this.classList.add("highlighted_drop_target");
}
}
// DOUBLE CLICK ACTION
PinList.ondblclick = function(event) {
if (event.target == this) {
ActionClickGroup(this, opt.dbclick_group);
}
}
// SHOW COLOR PICKER
document.getElementById("group_edit_font").onclick = function(event) {
if (event.which == 1) {
event.stopPropagation();
let ColorPicker = document.getElementById("color_picker");
ColorPicker.setAttribute("PickColor", this.id);
ColorPicker.value = "#"+RGBtoHex(this.style.backgroundColor);
ColorPicker.focus();
ColorPicker.click();
}
}
document.getElementById("color_picker").oninput = function(event) {
document.getElementById(this.getAttribute("PickColor")).style.backgroundColor = this.value;
}
document.getElementById("group_list").ondragleave = function(event) {
if (opt.open_tree_on_hover) {
clearTimeout(tt.DragOverTimer);
tt.DragOverId = "";
}
}
// CATCH KEYBOARD GLOBAL KEYS
document.body.onkeydown = function(event) {
// ctrl+a to select all
if (event.ctrlKey && event.which == 65) {
if (document.querySelector(".pin>.tab_header_hover") != null) {
document.querySelectorAll(".pin").forEach(function(s){
s.classList.add("selected_tab");
});
}
if (document.querySelector("#"+tt.active_group+" .tab>.tab_header_hover") != null) {
let rootId = document.querySelector("#"+tt.active_group+" .tab>.tab_header_hover").parentNode.parentNode.parentNode.id;
document.querySelectorAll("#ct"+rootId+">.tab").forEach(function(s){
s.classList.add("selected_tab");
});
}
}
// ctrl+i to invert selection
if (event.ctrlKey && event.which == 73) {
if (document.querySelector(".pin>.tab_header_hover") != null) {
document.querySelectorAll(".pin").forEach(function(s){
s.classList.toggle("selected_tab");
});
}
if (document.querySelector("#"+tt.active_group+" .tab>.tab_header_hover") != null) {
let rootId = document.querySelector("#"+tt.active_group+" .tab>.tab_header_hover").parentNode.parentNode.parentNode.id;
document.querySelectorAll("#ct"+rootId+">.tab").forEach(function(s){
s.classList.toggle("selected_tab");
});
}
}
// esc to deselect tabs
if (event.which == 27) {
DeselectTabs();
DeselectFolders();
}
// alt+g to toggle group bar
if (event.altKey && event.which == 71) {
GroupsToolbarToggle();
}
// new folder
if (event.which == 192 && event.which == 70 && event.which == 69) {
let FolderId = AddNewFolder({SetEvents: true});
ShowRenameFolderDialog(FolderId);
}
RefreshGUI();
}
document.body.ondragover = function(event) {
if (opt.debug) {
log("drag over: "+event.target.id);
}
event.preventDefault();
}
document.ondrop = function(event) {
if (opt.debug) {
log("dropped on window: "+tt.CurrentWindowId);
}
let Class = event.dataTransfer.getData("Class") ? event.dataTransfer.getData("Class") : "";
let Group = event.dataTransfer.getData("Group") ? JSON.parse(event.dataTransfer.getData("Group")) : {};
let DraggedTabNode = event.dataTransfer.getData("DraggedTabNode") ? event.dataTransfer.getData("DraggedTabNode") : false;
let TabsIds = event.dataTransfer.getData("TabsIds") ? JSON.parse(event.dataTransfer.getData("TabsIds")) : [];
let TabsIdsParents = event.dataTransfer.getData("TabsIdsParents") ? JSON.parse(event.dataTransfer.getData("TabsIdsParents")) : [];
let TabsIdsSelected = event.dataTransfer.getData("TabsIdsSelected") ? JSON.parse(event.dataTransfer.getData("TabsIdsSelected")) : [];
let Folders = event.dataTransfer.getData("Folders") ? JSON.parse(event.dataTransfer.getData("Folders")) : {};
let FoldersSelected = event.dataTransfer.getData("FoldersSelected") ? JSON.parse(event.dataTransfer.getData("FoldersSelected")) : [];
let SourceWindowId = event.dataTransfer.getData("SourceWindowId") ? JSON.parse(event.dataTransfer.getData("SourceWindowId")) : 0;
let target = document.querySelector(".highlighted_drop_target");
let ActiveGroup = document.getElementById(tt.active_group);
let Scroll = ActiveGroup.scrollTop;
clearTimeout(tt.DragOverTimer);
tt.DragOverId = "";
event.preventDefault();
if (SourceWindowId == tt.CurrentWindowId) {
if (Class == "group") {
DropToTarget({Class: Class, DraggedTabNode: DraggedTabNode, TargetNode: target, TabsIds: [], TabsIdsSelected: [], TabsIdsParents: [], Folders: {}, FoldersSelected: [], Group: Group, Scroll: Scroll});
} else {
DropToTarget({Class: Class, DraggedTabNode: DraggedTabNode, TargetNode: target, TabsIds: TabsIds, TabsIdsSelected: TabsIdsSelected, TabsIdsParents: TabsIdsParents, Folders: Folders, FoldersSelected: FoldersSelected, Group: Group, Scroll: Scroll});
}
} else {
FreezeSelected();
if (Object.keys(Group).length > 0) {
tt.groups[Group.id] = Object.assign({}, Group);
AppendGroupToList(Group.id, Group.name, Group.font, true);
}
if (Object.keys(Folders).length > 0) {
for (var folderId in Folders) {
AddNewFolder({folderId: folderId, ParentId: Folders[folderId].parent, Name: Folders[folderId].name, Index: Folders[folderId].index, ExpandState: Folders[folderId].expand, AdditionalClass: (FoldersSelected.indexOf(folderId) != -1 ? "selected_folder" : undefined), SetEvents: true});
chrome.runtime.sendMessage({ command: "remove_folder", folderId: folderId });
}
}
if (opt.debug) {
log("DragAndDrop: will now move tabs");
}
chrome.tabs.move(TabsIds, { windowId: tt.CurrentWindowId, index: -1 }, function(MovedTab) {
setTimeout(function() {
DropToTarget({Class: Class, DraggedTabNode: DraggedTabNode, TargetNode: target, TabsIds: TabsIds, TabsIdsSelected: TabsIdsSelected, TabsIdsParents: TabsIdsParents, Folders: Folders, FoldersSelected: FoldersSelected, Group: Group, Scroll: Scroll});
chrome.runtime.sendMessage({ command: "remove_group", groupId: Group.id });
}, 2000);
});
}
}
document.ondragleave = function(event) {
if (opt.debug) {
log("global dragleave");
}
RemoveHighlight();
if (opt.open_tree_on_hover) {
clearTimeout(tt.DragOverTimer);
tt.DragOverId = "";
}
}
document.ondragend = function(event) {
if (opt.open_tree_on_hover) {
clearTimeout(tt.DragOverTimer);
tt.DragOverId = "";
}
// log("document dragend");
// DETACHING TEMPORARILY DISABLED PLEASE USE MENU OR TOOLBAR!
// if (DragAndDrop.ComesFromWindowId == tt.CurrentWindowId && DragAndDrop.DroppedToWindowId == 0) {
// if ((browserId == "F" && ( event.screenX < event.view.mozInnerScreenX || event.screenX > (event.view.mozInnerScreenX + window.innerWidth) || event.screenY < event.view.mozInnerScreenY || event.screenY > (event.view.mozInnerScreenY + window.innerHeight)))|| (browserId != "F" && (event.pageX < 0 || event.pageX > window.outerWidth || event.pageY < 0 || event.pageY > window.outerHeight))) {
// log("dragged outside sidebar");
// if (tt.DragNodeClass == "tab") {
// Detach(DragAndDrop.TabsIds, {});
// }
// if (tt.DragNodeClass == "folder") {
// Detach(DragAndDrop.TabsIds, DragAndDrop.Folders);
// setTimeout(function() {
// SaveFolders();
// }, 500);
// }
// }
// }
setTimeout(function() {
CleanUpDragClasses();
chrome.runtime.sendMessage({command: "dragend"});
}, 500);
}
}
function BindTabsSwitchingToMouseWheel(Id) {
if (opt.debug) {
log("f: BindTabsSwitchingToMouseWheel, binding tabs switch to group: "+Id);
}
document.getElementById(Id).onwheel = function(event) {
event.preventDefault();
let prev = event.deltaY < 0;
if (prev) {
ActivatePrevTab();
} else {
ActivateNextTab();
}
}
}
function RemoveHighlight() {
document.querySelectorAll(".highlighted_drop_target").forEach(function(s){
if (opt.debug) {
log("removing highlight of: " + s.id);
}
s.classList.remove("before");
s.classList.remove("after");
s.classList.remove("inside");
s.classList.remove("highlighted_drop_target");
});
}
function RemoveHeadersHoverClass() {
document.querySelectorAll(".folder_header_hover, .tab_header_hover").forEach(function(s){
if (opt.debug) {
log("removing hover of: " + s.id);
}
s.classList.remove("folder_header_hover");
s.classList.remove("tab_header_hover");
});
}
function DropToTarget(p) { // Class: ("group", "tab", "folder"), DraggedTabNode: TabId, TargetNode: query node, TabsIdsSelected: arr of selected tabIds, TabsIds: arr of tabIds, TabsIdsParents: arr of parent tabIds, Folders: object with folders objects, FoldersSelected: arr of selected folders ids, Group: groupId, Scroll: bool
if (p.TargetNode != null) {
if (opt.debug) {
log("f: DropToTarget, DragNodeClass: "+p.Class+", TargetNode: "+p.TargetNode.id+", TabsIdsSelected: "+JSON.stringify(p.TabsIdsSelected)+", TabsIds: "+JSON.stringify(p.TabsIds)+", TabsIdsParents: "+JSON.stringify(p.TabsIdsParents)+", Folders: "+JSON.stringify(p.Folders)+", FoldersSelected: "+JSON.stringify(p.FoldersSelected) );
}
let ActiveGroup = document.getElementById(tt.active_group);
let pinTabs = false;
let SelectedTabsAppendTarget;
let FoldersSelectedAppendTarget;
if (p.Class == "tab") {
if (p.TargetNode.classList.contains("pin")) {
pinTabs = true;
if (p.TargetNode.classList.contains("before")) {
p.TabsIds.forEach(function(tabId){
InsterBeforeNode(document.getElementById(tabId), p.TargetNode);
});
}
if (p.TargetNode.classList.contains("after")) {
for (let i = p.TabsIds.length-1; i >= 0; i--) {
InsterAfterNode(document.getElementById(p.TabsIds[i]), p.TargetNode);
}
}
}
if (p.TargetNode.classList.contains("tab")) {
if (p.TargetNode.classList.contains("before")) {
p.TabsIdsSelected.forEach(function(tabId){
InsterBeforeNode(document.getElementById(tabId), p.TargetNode);
});
}
if (p.TargetNode.classList.contains("after")) {
for (let i = p.TabsIdsSelected.length-1; i >= 0; i--) {
InsterAfterNode(document.getElementById(p.TabsIdsSelected[i]), p.TargetNode);
}
}
if (p.TargetNode.classList.contains("inside")) {
SelectedTabsAppendTarget = p.TargetNode.childNodes[1];
}
ActiveGroup.scrollTop = p.Scroll;
}
if (p.TargetNode.id == "pin_list") {
pinTabs = true;
SelectedTabsAppendTarget = p.TargetNode;
}
if (p.TargetNode.classList.contains("group")) {
SelectedTabsAppendTarget = p.TargetNode.childNodes[1];
ActiveGroup.scrollTop = p.Scroll;
}
if (p.TargetNode.classList.contains("folder")) {
SelectedTabsAppendTarget = p.TargetNode.childNodes[2];
ActiveGroup.scrollTop = p.Scroll;
}
if (p.TargetNode.classList.contains("group_button")) { // dropped on group button (group list)
SelectedTabsAppendTarget = document.getElementById("ct" + (p.TargetNode.id.substr(1)));
}
}
if (p.Class == "folder") {
if (p.TargetNode.classList.contains("folder")) { // dropped on folder
if (p.TargetNode.classList.contains("before")) {
p.FoldersSelected.forEach(function(folderId){
InsterBeforeNode(document.getElementById(folderId), p.TargetNode);
});
}
if (p.TargetNode.classList.contains("after")) {
for(let i = p.FoldersSelected.length-1; i >= 0; i--) {
InsterAfterNode(document.getElementById(p.FoldersSelected[i]), p.TargetNode);
}
}
if (p.TargetNode.classList.contains("inside")) {
FoldersSelectedAppendTarget = p.TargetNode.childNodes[1];
}
ActiveGroup.scrollTop = p.Scroll;
}
if (p.TargetNode.classList.contains("group")) {
FoldersSelectedAppendTarget = p.TargetNode.childNodes[0];
ActiveGroup.scrollTop = p.Scroll;
}
if (p.TargetNode.classList.contains("group_button")) { // dropped on group button (group list)
FoldersSelectedAppendTarget = document.getElementById("cf" + p.TargetNode.id.substr(1));
}
setTimeout(function() {
SaveFolders();
}, 600);
}
if (p.TargetNode.classList.contains("group_button") && (p.Class == "tab" || p.Class == "folder")) {
chrome.tabs.query({currentWindow: true, active: true}, function(activeTab) {
let Tab = document.getElementById(activeTab[0].id);
if (Tab != null && p.TabsIds.indexOf(activeTab[0].id) != -1) {
SetActiveGroup(p.TargetNode.id.substr(1), false, false);
SetActiveTab(activeTab[0].id, true);
}
});
}
if (p.Class == "group") {
if (p.TargetNode.classList.contains("before")) {
InsterBeforeNode(document.getElementById("_"+p.Group.id), p.TargetNode);
}
if (p.TargetNode.classList.contains("after")) {
InsterAfterNode(document.getElementById("_"+p.Group.id), p.TargetNode);
}
UpdateBgGroupsOrder();
RearrangeGroupsLists();
if (opt.syncro_tabbar_groups_tabs_order) {
tt.schedule_rearrange_tabs++;
}
}
if (FoldersSelectedAppendTarget) {
p.FoldersSelected.forEach(function(folderId){
AppendToNode(document.getElementById(folderId), FoldersSelectedAppendTarget);
});
}
if (SelectedTabsAppendTarget) {
p.TabsIdsSelected.forEach(function(tabId){
AppendToNode(document.getElementById(tabId), SelectedTabsAppendTarget);
});
}
// recheck new structure
if (Object.keys(p.Folders).length > 0) {
for (var folderId in p.Folders) {
if (p.FoldersSelected.indexOf(folderId) == -1) {
let Folder = document.getElementById(folderId);
if (Folder != null && Folder.parentNode.id != "cf" + p.Folders[folderId].parent) {
let FolderParent = document.getElementById("cf" + p.Folders[folderId].parent);
if (FolderParent != null) {
FolderParent.appendChild(Folder);
}
}
}
}
}
if (p.TabsIds.length) {
if (pinTabs) {
for (var ind = 0; ind < p.TabsIds.length; ind++) {
let Tab = document.getElementById(p.TabsIds[ind]);
if (Tab != null && Tab.parentNode.id != "pin_list") {
document.getElementById("pin_list").appendChild(Tab);
}
}
} else {
for (var ind = 0; ind < p.TabsIds.length; ind++) {
if (p.TabsIdsSelected.indexOf(p.TabsIds[ind]) == -1) {
let Tab = document.getElementById(p.TabsIds[ind]);
let TabParent = document.getElementById(p.TabsIdsParents[ind]);
if (TabParent != null && Tab != null && TabParent.id != Tab.parentNode.id) {
TabParent.appendChild(Tab);
}
}
}
}
}
SetMultiTabsClass(p.TabsIds, pinTabs);
p.TabsIdsSelected.forEach(function(selectedTabId) {
let selectedTab = document.getElementById(selectedTabId);
if (selectedTab != null) {
selectedTab.classList.add("selected_tab");
}
});
if (p.DraggedTabNode) {
let tabNode = document.getElementById(p.DraggedTabNode);
if (tabNode != null) {
tabNode.classList.add("selected_temporarly");
}
}
if (opt.syncro_tabbar_tabs_order && p.TabsIds[0] != undefined) {
let tabIds = Array.prototype.map.call(document.querySelectorAll(".pin, .tab"), function(s){
return parseInt(s.id);
});
if (opt.debug) {
log( "f: DropToTarget, will Syncro tabbar tabs order, TabsIds array is:"+JSON.stringify(p.TabsIds) );
}
chrome.tabs.move(p.TabsIds, {index: tabIds.indexOf(p.TabsIds[0])});
setTimeout(function() {
tt.schedule_rearrange_tabs++;
}, 500);
}
}
KeepOnlyOneActiveTabInGroup();
setTimeout(function() {
RefreshExpandStates();
RefreshCounters();
tt.schedule_update_data++;
RefreshGUI();
EmptyDragAndDrop();
if (opt.debug) {
log("DropToTarget END");
}
}, 500);
setTimeout(function() {
CleanUpDragClasses();
RemoveHighlight();
}, 100);
}
function FreezeSelected() {
document.querySelectorAll(".selected_tab").forEach(function(s){
if (opt.debug) {
log("freezing selected tab: " + s.id);
}
s.classList.add("selected_frozen");
s.classList.remove("selected_tab");
s.classList.remove("selected_last");
});
document.querySelectorAll(".selected_folder").forEach(function(s){
if (opt.debug) {
log("freezing selected folder: " + s.id);
}
s.classList.add("selected_folder_frozen");
s.classList.remove("selected_folder");
});
}
function CleanUpDragClasses() {
if (opt.debug) {
log("f: CleanUpDragClasses, unfreezing and removing temporary classes...");
}
document.querySelectorAll(".selected_frozen").forEach(function(s){
s.classList.add("selected_tab");
s.classList.remove("selected_frozen");
});
document.querySelectorAll(".selected_temporarly").forEach(function(s){
s.classList.remove("selected_tab");
s.classList.remove("selected_temporarly");
});
document.querySelectorAll(".selected_folder_frozen").forEach(function(s){
s.classList.add("selected_folder");
s.classList.remove("selected_folder_frozen");
});
document.querySelectorAll(".selected_folder_temporarly").forEach(function(s){
s.classList.remove("selected_folder");
s.classList.remove("selected_folder_temporarly");
});
document.querySelectorAll(".tab_header_hover").forEach(function(s){
s.classList.remove("tab_header_hover");
});
document.querySelectorAll(".folder_header").forEach(function(s){
s.classList.remove("folder_header_hover");
});
document.querySelectorAll(".dragged_tree").forEach(function(s){
s.classList.remove("dragged_tree");
});
document.querySelectorAll(".dragged_parents").forEach(function(s){
s.classList.remove("dragged_parents");
});
}
function EmptyDragAndDrop() {
if (opt.debug) {
log("f: EmptyDragAndDrop and removing DragNodeClass...");
}
tt.DragNodeClass = "";
tt.DragTreeDepth = 0;
}

22
scripts/file.js Normal file
View File

@ -0,0 +1,22 @@
function File_ShowOpenFileDialog(extension) {
let inp = DOM_New("input", document.getElementById("body"), {id: "file_import", type: "file", accept: extension}, {display: "none"});
inp.click();
return inp;
}
function File_SaveFile(filename, extension, data) {
if (browserId == "V") {
chrome.tabs.create({url: "vivaldi/save_file.html"}, async function(tab) {
setTimeout(function() {
chrome.runtime.sendMessage({command: "save_file", filename: filename, extension: extension, data: data});
}, 500);
});
} else {
let file = new File([JSON.stringify(data)], filename + "." + extension, {type: "text/" + extension + ";charset=utf-8"});
let savelink = DOM_New("a", document.getElementById("body"), {href:URL.createObjectURL(file), fileSize: file.size, target: "_blank", type: "file", download: (filename + "." + extension)}, {display: "none"});
savelink.click();
setTimeout(function() {
savelink.parentNode.removeChild(savelink);
}, 60000);
}
}

View File

@ -1,504 +1,283 @@
// 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/
function AddNewFolder(p) { // folderId: string, ParentId: string, Name: string, Index: int, ExpandState: ("o","c"), AdditionalClass: string, SetEvents: bool
let newId = p.folderId ? p.folderId : GenerateNewFolderID();
tt.folders[newId] = { id: newId, parent: (p.ParentId ? p.ParentId : ""), index: (p.Index ? p.Index : 0), name: (p.Name ? p.Name : labels.noname_group), expand: (p.ExpandState ? p.ExpandState : "") };
if (opt.debug) {
log("f: AddNewFolder, folder: "+JSON.stringify(tt.folders[newId]));
}
AppendFolder(newId, labels.noname_group, (p.ParentId ? p.ParentId : ""), undefined, p.SetEvents, p.AdditionalClass);
SaveFolders();
RefreshCounters();
RefreshExpandStates();
return newId;
function Folders_AddNewFolder(p) { // folderId: string, ParentId: string, Name: string, Index: int, ExpandState: ("o","c"), AdditionalClass: string, SetEvents: bool
let newId = p.folderId ? p.folderId : Folders_GenerateNewFolderID();
tt.folders[newId] = {id: newId, parent: (p.ParentId ? p.ParentId : ""), index: (p.Index ? p.Index : 0), name: (p.Name ? p.Name : labels.noname_group), expand: (p.ExpandState ? p.ExpandState : "")};
Folders_AppendFolder({folderId: newId, Name: tt.folders[newId].name, InsertAfterId: p.InsertAfterId, ParentId: p.ParentId, ExpandState: p.ExpandState, SkipSetEvents: p.SkipSetEvents, AdditionalClass: p.AdditionalClass});
Folders_SaveFolders();
DOM_RefreshCounters();
DOM_RefreshExpandStates();
return newId;
}
function AppendFolder(folderId, Name, ParentId, Expand, SetEvents, AdditionalClass) {
if (opt.debug) {
log("f: AppendFolder, folder: "+JSON.stringify(tt.folders[folderId]));
}
let ClassList = "folder ";
if (AdditionalClass != undefined) {
ClassList = ClassList + AdditionalClass;
}
if (document.getElementById(folderId) == null) {
let fd = document.createElement("div"); fd.className = ClassList; if (Expand) { fd.className += Expand } fd.id = folderId; // FOLDER
let fh = document.createElement("div"); fh.className = (opt.always_show_close && !opt.never_show_close) ? "folder_header close_show" : "folder_header"; fh.id = "folder_header"+folderId; if (SetEvents) {fh.draggable = true;} fd.appendChild(fh); // HEADER
let ex = document.createElement("div"); ex.className = "folder_icon"; ex.id = "fop"+folderId; fh.appendChild(ex);
let ftbc = document.createElement("div"); ftbc.className = "folder_counter"; ftbc.id = "folder_counter"+folderId; fh.appendChild(ftbc); // TABS COUNTER
let fbcn = document.createElement("div"); fbcn.className = "counter_number"; fbcn.id = "counter_number"+folderId; ftbc.appendChild(fbcn); // TABS COUNTER NUMBER
let ft = document.createElement("div"); ft.className = "folder_title"; ft.id = "folder_title"+folderId; ft.textContent = Name; fh.appendChild(ft); // TITLE
let cf = document.createElement("div"); cf.className = "children_folders"; cf.id = "cf"+folderId; fd.appendChild(cf);
let ct = document.createElement("div"); ct.className = "children_tabs"; ct.id = "ct"+folderId; fd.appendChild(ct);
let di = document.createElement("div"); di.className = "drag_indicator"; di.id = "di"+folderId; fd.appendChild(di); // DROP TARGET INDICATOR
let cl = undefined;
if (!opt.never_show_close) {
cl = document.createElement("div"); cl.className = "close"; cl.id = "close"+folderId; fh.appendChild(cl); // CLOSE BUTTON
let ci = document.createElement("div"); ci.className = "close_img"; ci.id = "close_img"+folderId; cl.appendChild(ci);
}
if (SetEvents) {
ct.ondblclick = function(event) {
if (event.target == this) {
ActionClickGroup(this.parentNode, opt.dbclick_group);
}
}
cf.ondblclick = function(event) {
if (event.target == this) {
ActionClickGroup(this.parentNode, opt.dbclick_group);
}
}
cf.onclick = function(event) {
if (event.target == this && event.which == 1) {
DeselectFolders();
DeselectTabs();
}
}
ct.onclick = function(event) {
if (event.target == this && event.which == 1) {
DeselectFolders();
DeselectTabs();
}
}
cf.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.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);
}
}
}
if (!opt.never_show_close && cl) {
cl.onmousedown = function(event) {
event.stopImmediatePropagation();
if (event.which != 3) {
RemoveFolder(this.parentNode.parentNode.id);
}
}
cl.onmouseenter = function(event) {
this.classList.add("close_hover");
}
cl.onmouseleave = function(event) {
this.classList.remove("close_hover");
}
}
fh.onclick = function(event) {
// SELECT FOLDER
if (event.which == 1 && !event.shiftKey) {
DeselectTabs();
if (!event.ctrlKey && this.parentNode.classList.contains("selected_folder") == false) {
DeselectFolders();
}
if (event.ctrlKey) {
this.parentNode.classList.toggle("selected_folder");
}
}
}
fh.onmousedown = function(event) {
if (document.getElementById("main_menu").style.top != "-1000px") {
HideMenus();
}
if (event.which == 2) {
event.preventDefault();
ActionClickFolder(this.parentNode, opt.midclick_folder);
}
// SHOW FOLDER MENU
if (event.which == 3) {
ShowFolderMenu(this.parentNode, event);
}
}
// edit folder
fh.ondblclick = function(event) {
if (event.which == 1 && !event.shiftKey && !event.ctrlKey && event.target.classList.contains("folder_header")) {
ActionClickFolder(this.parentNode, opt.dbclick_folder);
}
}
fh.ondragstart = function(event) { // DRAG START
FolderStartDrag(this, event);
}
fh.ondragenter = function(event) {
this.classList.remove("folder_header_hover");
}
fh.onmouseover = function(event) {
this.classList.add("folder_header_hover");
if (opt.never_show_close == false && opt.always_show_close == false) {
this.classList.add("close_show");
}
}
fh.onmouseleave = function(event) {
this.classList.remove("folder_header_hover");
if (opt.never_show_close == false && opt.always_show_close == false) {
this.classList.remove("close_show");
}
}
fh.ondragleave = function(event) {
RemoveHighlight();
}
fh.ondragover = function(event) {
FolderDragOver(this, event);
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);
}
}
}
ex.onmousedown = function(event) {
event.stopPropagation();
if (document.getElementById("main_menu").style.top != "-1000px") {
HideMenus();
}
// EXPAND/COLLAPSE FOLDER
if (event.which == 1 && !event.shiftKey && !event.ctrlKey && event.target == this) {
event.stopPropagation();
EventExpandBox(this.parentNode.parentNode);
RefreshExpandStates();
RefreshCounters();
}
}
}
if (ParentId == "" || ParentId == undefined || document.getElementById("cf"+ParentId) == null) {
document.getElementById("cf"+tt.active_group).appendChild(fd);
} else {
document.getElementById("cf"+ParentId).appendChild(fd);
}
}
function Folders_AppendFolder(p) { // folderId: string, ParentId: string, Name: string, ExpandState: ("o","c"), AdditionalClass: string, SetEvents: bool
let ClassList = "folder";
if (p.ExpandState) ClassList += " " + p.ExpandState;
if (p.AdditionalClass != undefined) ClassList += " " + p.AdditionalClass;
if (document.getElementById(p.folderId) == null) {
let DIV_folder = DOM_New("div", undefined, {id: p.folderId, className: ClassList});
let DIV_header = DOM_New("div", DIV_folder, {id: ("folder_header_" + p.folderId), className: ((opt.always_show_close && !opt.never_show_close) ? "folder_header close_show" : "folder_header"), draggable: (!p.SkipSetEvents ? true : false)});
let DIV_expand = DOM_New("div", DIV_header, {id: ("folder_expand_" + p.folderId), className: "folder_icon"});
let DIV_counter = DOM_New("div", DIV_header, {id: ("folder_counter_" + p.folderId), className: "folder_counter"});
DOM_New("div", DIV_counter, {id: ("folder_counter_number_" + p.folderId), className: "counter_number"});
DOM_New("div", DIV_header, {id: ("folder_title_" + p.folderId), className: "folder_title", textContent: p.Name});
let DIV_children = DOM_New("div", DIV_folder, {id: ("°" + p.folderId), className: "children"});
DOM_New("div", DIV_folder, {id: (p.folderId + "_drag_indicator"), className: "drag_indicator"});
let DIV_close_button = DOM_New("div", DIV_header, {id: ("close" + p.folderId), className : (opt.never_show_close ? "close hidden" : "close")});
DOM_New("div", DIV_close_button, {id: ("close_img" + p.folderId), className: (opt.never_show_close ? "close_img hidden" : "close_img")});
if (!p.SkipSetEvents) {
DIV_children.ondblclick = function(event) {
if (event.target == this) Groups_ActionClickGroup(this.parentNode, opt.dbclick_group);
}
DIV_children.onclick = function(event) {
if (event.target == this && event.which == 1) DOM_Deselect();
}
DIV_children.onmousedown = function(event) {
event.stopImmediatePropagation();
if (event.target == this) {
if (event.which == 2 && event.target == this) Groups_ActionClickGroup(this.parentNode, opt.midclick_group);
if (event.which == 3) Menu_ShowFGlobalMenu(event);
}
}
if (!opt.never_show_close) {
DIV_close_button.onmousedown = function(event) {
event.stopImmediatePropagation();
if (event.which != 3) Folders_RemoveFolder(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.onclick = function(event) {
if (event.which == 1 && !event.shiftKey && !event.ctrlKey && event.target.classList.contains("folder_header")) DOM_Deselect();
}
DIV_header.onmousedown = function(event) {
event.stopImmediatePropagation();
if (tt.DOMmenu.style.top != "-1000px") Menu_HideMenus();
if (event.which == 1) DOM_Select(event, this.parentNode);
if (event.which == 2) {
event.preventDefault();
Folders_ActionClickFolder(this.parentNode, opt.midclick_folder);
}
if (event.which == 3) Menu_ShowFolderMenu(this.parentNode, event); // SHOW FOLDER MENU
}
DIV_header.ondblclick = function(event) { // edit folder
if (event.which == 1 && !event.shiftKey && !event.ctrlKey && event.target.classList.contains("folder_header")) Folders_ActionClickFolder(this.parentNode, opt.dbclick_folder);
}
DIV_header.ondragstart = function(event) { // DRAG START
event.stopPropagation();
event.dataTransfer.setDragImage(document.getElementById("DragImage"), 0, 0);
event.dataTransfer.setData("text", "");
event.dataTransfer.setData("SourceWindowId", tt.CurrentWindowId);
DOM_CleanUpDragAndDrop();
tt.Dragging = true;
tt.DraggingGroup = false;
tt.DragTreeDepth = -1;
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 : "")});
}
}
let DraggedFolderParents = DOM_GetParentsByClass(this.parentNode, "folder");
for (let s of DraggedFolderParents) {
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("folder_header_hover");
}
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_header.onmouseover = function(event) {
this.classList.add("folder_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("folder_header_hover");
if (opt.never_show_close == false && opt.always_show_close == false) this.classList.remove("close_show");
}
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("before") == false && event.layerY < this.clientHeight / 3) {
DOM_RemoveHighlight();
DOM_SetClasses(this.parentNode, ["before", "highlighted_drop_target"], ["inside", "after"], []);
}
if (this.parentNode.classList.contains("inside") == false && event.layerY > this.clientHeight / 3 && event.layerY <= 2 * (this.clientHeight / 3)) {
DOM_RemoveHighlight();
DOM_SetClasses(this.parentNode, ["inside", "highlighted_drop_target"], ["before", "after"], []);
}
if (this.parentNode.classList.contains("after") == false && this.parentNode.classList.contains("o") == false && event.layerY > 2 * (this.clientHeight / 3)) {
DOM_RemoveHighlight();
DOM_SetClasses(this.parentNode, ["after", "highlighted_drop_target"], ["inside", "before"], []);
}
}
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_expand.onmousedown = function(event) {
event.stopPropagation();
if (tt.DOMmenu.style.top != "-1000px") Menu_HideMenus();
if (event.which == 1 && !event.shiftKey && !event.ctrlKey && event.target == this) { // EXPAND/COLLAPSE FOLDER
event.stopPropagation();
DOM_EventExpandBox(this.parentNode.parentNode);
DOM_RefreshExpandStates();
DOM_RefreshCounters();
}
}
}
if (p.ParentId == "pin_list" || p.ParentId == "" || p.ParentId == undefined || document.getElementById("°" + p.ParentId) == null) {
document.getElementById("°" + tt.active_group).appendChild(DIV_folder);
} else {
document.getElementById("°" + p.ParentId).appendChild(DIV_folder);
}
if (p.InsertAfterId) {
let After = document.getElementById(p.InsertAfterId);
if (After != null) DOM_InsterAfterNode(DIV_folder, After);
}
}
}
function GenerateNewFolderID() {
let newID = "";
while (newID == "") {
newID = "f_"+GenerateRandomID();
if (document.getElementById(newID) != null) {
newID = "";
}
}
return newID;
function Folders_GenerateNewFolderID() {
let newID = "";
while (newID == "") {
newID = "f_" + GenerateRandomID();
if (document.getElementById(newID) != null) newID = "";
}
return newID;
}
function AppendFolders(Folders) {
if (opt.debug) {
log("f: AppendFolders, Folders: "+JSON.stringify(Folders));
}
for (let folderId in Folders) {
AppendFolder(folderId, Folders[folderId].name, Folders[folderId].parent, Folders[folderId].expand, true, undefined);
}
for (let folderId in Folders) {
let f = document.getElementById(folderId);
let parent = document.getElementById("cf"+Folders[folderId].parent);
if (f != null && parent != null && Folders[folderId].parent != f.parentNode.parentNode.id) {
parent.appendChild(f);
}
}
function Folders_PreAppendFolders(folders) {
for (let folderId in folders) {Folders_AppendFolder({folderId: folderId, Name: folders[folderId].name, ParentId: "tab_list", ExpandState: folders[folderId].expand});}
}
function SaveFolders() {
document.querySelectorAll(".folder").forEach(function(s){
tt.folders[s.id].parent = s.parentNode.parentNode.id;
tt.folders[s.id].index = Array.from(s.parentNode.children).indexOf(s);
tt.folders[s.id].expand = (s.classList.contains("c") ? "c" : (s.classList.contains("o") ? "o" : ""));
});
chrome.runtime.sendMessage({command: "save_folders", folders: tt.folders, windowId: tt.CurrentWindowId});
function Folders_AppendFolders(folders) {
for (let folderId in folders) {
let f = document.getElementById(folderId);
let parent = document.getElementById("°" + folders[folderId].parent);
if (f != null && parent != null && folders[folderId].parent != f.parentNode.parentNode.id && parent.parentNode.classList.contains("pin") == false) parent.appendChild(f);
}
}
function RearrangeFolders(first_loop) {
if (opt.debug) {
log("f: RearrangeFolders");
}
document.querySelectorAll(".folder").forEach(function(s){
if (tt.folders[s.id] && s.parentNode.childNodes[tt.folders[s.id].index]) {
let Ind = Array.from(s.parentNode.children).indexOf(s);
if (Ind > tt.folders[s.id].index) {
InsterBeforeNode(s, s.parentNode.childNodes[tt.folders[s.id].index]);
} else {
InsterAfterNode(s, s.parentNode.childNodes[tt.folders[s.id].index]);
}
}
let newInd = Array.from(s.parentNode.children).indexOf(s);
if (tt.folders[s.id] && newInd != tt.folders[s.id].index && first_loop) {
RearrangeFolders(false);
}
});
function Folders_SaveFolders() {
let query = document.querySelectorAll(".folder");
for (let s of query) {
tt.folders[s.id].parent = s.parentNode.parentNode.id;
tt.folders[s.id].index = Array.from(s.parentNode.children).indexOf(s);
tt.folders[s.id].expand = (s.classList.contains("c") ? "c" : (s.classList.contains("o") ? "o" : ""));
}
chrome.runtime.sendMessage({command: "save_folders", folders: tt.folders, windowId: tt.CurrentWindowId});
}
function RemoveFolder(FolderId) {
if (opt.debug) {
log("f: RemoveFolder, folderId "+FolderId);
}
let folder = document.getElementById(FolderId);
if (folder != null) {
let CF = folder.childNodes[1]; // CF stands for DIV with children folders
let CT = folder.childNodes[2]; // CT stands for DIV with children tabs
if (opt.promote_children == true) {
if (opt.promote_children_in_first_child == true && CF.children.length > 0) {
let FirstFolderChild = CF.firstChild;
folder.parentNode.insertBefore(FirstFolderChild, folder);
let NewCF = FirstFolderChild.childNodes[1];
while (CF.firstChild) {
NewCF.appendChild(CF.firstChild);
}
if (CT.childNodes.length > 0) {
let NewCT = FirstFolderChild.childNodes[2];
while (CT.firstChild) {
NewCT.appendChild(CT.firstChild);
}
}
} else {
let NewCT = document.getElementById("ct"+folder.parentNode.parentNode.id);
// let NewCT = folder.parentNode.parentNode.childNodes[2];
while (CT.firstChild) {
NewCT.appendChild(CT.firstChild);
}
while (CF.lastChild) {
folder.parentNode.insertBefore(CF.lastChild, folder);
}
}
} else {
document.querySelectorAll("#"+FolderId+" .tab").forEach(function(s){
chrome.tabs.remove(parseInt(s.id), null);
});
document.querySelectorAll("#"+FolderId+" .folder").forEach(function(s){
delete tt.folders[s.id];
});
}
folder.parentNode.removeChild(folder);
delete tt.folders[FolderId];
RefreshExpandStates();
chrome.runtime.sendMessage({command: "save_folders", folders: tt.folders, windowId: tt.CurrentWindowId});
}
function Folders_RemoveFolder(FolderId) {
if (opt.debug) Utils_log("f: RemoveFolder, folderId " + FolderId);
let folder = document.getElementById(FolderId);
if (folder != null) {
if (opt.promote_children == true) {
if (opt.promote_children_in_first_child == true && folder.childNodes[1].childNodes.length > 1) {
DOM_PromoteChildrenToFirstChild(folder);
} else {
let Children = folder.childNodes[1];
while (Children.lastChild) {
DOM_InsterAfterNode(Children.lastChild, folder);
}
}
} else {
let query = document.querySelectorAll("#" + FolderId + " .tab");
for (let s of query) {
chrome.tabs.remove(parseInt(s.id), null);
}
query = document.querySelectorAll("#" + FolderId + " .folder");
for (let s of query) {
delete tt.folders[s.id];
}
}
folder.parentNode.removeChild(folder);
delete tt.folders[FolderId];
DOM_RefreshExpandStates();
chrome.runtime.sendMessage({command: "save_folders", folders: tt.folders, windowId: tt.CurrentWindowId});
}
}
function ShowRenameFolderDialog(FolderId) { // Rename folder popup
if (opt.debug) {
log("f: ShowRenameFolderDialog, folderId "+FolderId);
}
HideRenameDialogs();
if (tt.folders[FolderId]) {
let name = document.getElementById("folder_edit_name");
name.value = tt.folders[FolderId].name;
let folderEditDialog = document.getElementById("folder_edit");
folderEditDialog.setAttribute("FolderId", FolderId);
folderEditDialog.style.display = "block";
folderEditDialog.style.top = document.getElementById("toolbar").getBoundingClientRect().height + document.getElementById("pin_list").getBoundingClientRect().height + 8 + "px";
// folderEditDialog.style.left = "22px";
folderEditDialog.style.left = "";
setTimeout(function(){
document.getElementById("folder_edit_name").select();
},5);
}
function Folders_ShowRenameFolderDialog(FolderId) { // Rename folder popup
if (opt.debug) Utils_log("f: ShowRenameFolderDialog, folderId " + FolderId);
DOM_HideRenameDialogs();
if (tt.folders[FolderId]) {
let name = document.getElementById("folder_edit_name");
name.value = tt.folders[FolderId].name;
let folderEditDialog = document.getElementById("folder_edit");
folderEditDialog.setAttribute("FolderId", FolderId);
DOM_SetStyle(folderEditDialog, {display: "block", left: "", top: document.getElementById("toolbar").getBoundingClientRect().height + document.getElementById("pin_list").getBoundingClientRect().height + 8 + "px"});
setTimeout(function() {document.getElementById("folder_edit_name").select();}, 5);
}
}
function FolderRenameConfirm() { // when pressed OK in folder popup
let name = document.getElementById("folder_edit_name");
let FolderId = document.getElementById("folder_edit").getAttribute("FolderId");
// name.value = name.value.replace(/[\f\n\r\v\t\<\>\+\-\(\)\.\,\;\:\~\/\|\?\@\!\"\'\£\$\%\&\^\#\=\*\[\]]?/gi, "");
tt.folders[FolderId].name = name.value;
document.getElementById("folder_title" + FolderId).textContent = name.value;
HideRenameDialogs();
if (opt.debug) {
log("f: FolderRenameConfirm, folderId "+FolderId+", name: "+name.value);
}
chrome.runtime.sendMessage({command: "save_folders", folders: tt.folders, windowId: tt.CurrentWindowId});
RefreshCounters();
function Folders_FolderRenameConfirm() { // when pressed OK in folder popup
let name = document.getElementById("folder_edit_name");
let FolderId = document.getElementById("folder_edit").getAttribute("FolderId");
tt.folders[FolderId].name = name.value;
document.getElementById("folder_title_"+FolderId).textContent = name.value;
DOM_HideRenameDialogs();
if (opt.debug) Utils_log("f: FolderRenameConfirm, folderId " + FolderId + ", name: " + name.value);
chrome.runtime.sendMessage({command: "save_folders", folders: tt.folders, windowId: tt.CurrentWindowId});
DOM_RefreshCounters();
}
function DeselectFolders() {
if (opt.debug) {
log("f: DeselectFolders");
}
document.querySelectorAll("#"+tt.active_group+" .selected_folder").forEach(function(s){
s.classList.remove("selected_folder");
});
}
function ActionClickFolder(FolderNode, bgOption) {
if (opt.debug) {
log("f: ActionClickFolder, folderId "+FolderNode.id+", bgOption: "+bgOption);
}
if (bgOption == "rename_folder") {
ShowRenameFolderDialog(FolderNode.id);
}
if (bgOption == "new_folder") {
let FolderId = AddNewFolder({ParentId: FolderNode.id, SetEvents: true});
ShowRenameFolderDialog(FolderId);
}
if (bgOption == "new_tab") {
OpenNewTab(false, FolderNode.id);
}
if (bgOption == "expand_collapse") {
EventExpandBox(FolderNode);
}
if (bgOption == "close_folder") {
RemoveFolder(FolderNode.id);
}
if (bgOption == "unload_folder") {
let tabsArr = [];
document.querySelectorAll("#"+FolderNode.id+" .tab").forEach(function(s){
tabsArr.push(parseInt(s.id));
});
DiscardTabs(tabsArr);
}
}
function FolderStartDrag(Node, event) {
if (opt.debug) {
log("f: FolderStartDrag, folderId "+Node.id);
}
event.stopPropagation();
event.dataTransfer.setDragImage(document.getElementById("DragImage"), 0, 0);
event.dataTransfer.setData("text", "");
event.dataTransfer.setData("SourceWindowId", tt.CurrentWindowId);
CleanUpDragClasses();
EmptyDragAndDrop();
tt.DragNodeClass = "folder";
let TabsIds = [];
let TabsIdsParents = [];
let Folders = {};
let FoldersSelected = [];
if (Node.parentNode.classList.contains("selected_folder")) {
document.querySelectorAll(".group:not(#"+tt.active_group+") .selected_folder").forEach(function(s){
s.classList.add("selected_folder_frozen");
s.classList.remove("selected_folder");
});
} else {
FreezeSelected();
Node.parentNode.classList.add("selected_folder_temporarly");
Node.parentNode.classList.add("selected_folder");
}
RemoveHeadersHoverClass();
document.querySelectorAll("[id='"+Node.parentNode.id+"'], [id='"+Node.parentNode.id+"'] .folder, [id='"+Node.parentNode.id+"'] .tab").forEach(function(s){
s.classList.add("dragged_tree");
});
if (opt.max_tree_drag_drop_folders || opt.max_tree_depth >= 0) {
document.querySelectorAll(".dragged_tree .folder").forEach(function(s){
let parents = GetParentsByClass(s.parentNode, "dragged_tree");
if (parents.length > tt.DragTreeDepth) {
tt.DragTreeDepth = parents.length;
}
});
} else {
tt.DragTreeDepth = -1;
}
// REST OF SELECTED FOLDERS+TABS THAT WILL BE DRAGGED
document.querySelectorAll(".selected_folder, .selected_folder .tab, .selected_folder .folder").forEach(function(s){
s.classList.add("dragged_tree");
});
document.querySelectorAll("#"+tt.active_group+" .selected_folder").forEach(function(s){
FoldersSelected.push(s.id);
Folders[s.id] = Object.assign({}, tt.folders[s.id]);
let Fchildren = document.querySelectorAll("#cf"+s.id+" .folder");
Fchildren.forEach(function(fc){
Folders[fc.id] = Folders[fc.id] = Object.assign({}, tt.folders[fc.id]);
});
let Tchildren = document.querySelectorAll("#ct"+s.id+" .tab");
Tchildren.forEach(function(tc){
TabsIds.push(parseInt(tc.id));
TabsIdsParents.push(tc.parentNode.id);
});
});
let DraggedFolderParents = GetParentsByClass(Node, "folder");
DraggedFolderParents.forEach(function(s){
s.classList.add("dragged_parents");
});
event.dataTransfer.setData("Class", "folder");
event.dataTransfer.setData("TabsIds", JSON.stringify(TabsIds));
event.dataTransfer.setData("TabsIdsParents", JSON.stringify(TabsIdsParents));
event.dataTransfer.setData("Folders", JSON.stringify(Folders));
event.dataTransfer.setData("FoldersSelected", JSON.stringify(FoldersSelected));
chrome.runtime.sendMessage({
command: "drag_drop",
DragNodeClass: "folder",
DragTreeDepth: tt.DragTreeDepth
});
}
function FolderDragOver(Node, event) {
if (opt.debug) {
log("f: debug, folderId "+Node.id);
}
if (Node.parentNode.classList.contains("dragged_tree") == false) {
let PDepth = (GetParentsByClass(Node, "folder")).length + tt.DragTreeDepth;
let PIsGroup = Node.parentNode.parentNode.parentNode.classList.contains("group");
let PIsDraggedParents = Node.parentNode.classList.contains("dragged_parents");
if (tt.DragNodeClass == "folder" && 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_folders == false)) {
RemoveHighlight();
Node.parentNode.classList.remove("inside");
Node.parentNode.classList.remove("after");
Node.parentNode.classList.add("before");
Node.parentNode.classList.add("highlighted_drop_target");
}
if (tt.DragNodeClass == "folder" && 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_folders == false)) {
RemoveHighlight();
Node.parentNode.classList.remove("before");
Node.parentNode.classList.remove("after");
Node.parentNode.classList.add("inside");
Node.parentNode.classList.add("highlighted_drop_target");
}
if (tt.DragNodeClass == "folder" && 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_folders == false)) {
RemoveHighlight();
Node.parentNode.classList.remove("inside");
Node.parentNode.classList.remove("before");
Node.parentNode.classList.add("after");
Node.parentNode.classList.add("highlighted_drop_target");
}
if (tt.DragNodeClass == "tab" && Node.parentNode.classList.contains("inside") == false && (PDepth <= opt.max_tree_depth || opt.max_tree_depth < 0 || PIsDraggedParents || opt.max_tree_drag_drop_folders == false)) {
RemoveHighlight();
Node.parentNode.classList.remove("before");
Node.parentNode.classList.remove("after");
Node.parentNode.classList.add("inside");
Node.parentNode.classList.add("highlighted_drop_target");
}
}
function Folders_ActionClickFolder(FolderNode, bgOption) {
if (opt.debug) Utils_log("f: ActionClickFolder, folderId " + FolderNode.id + ", bgOption: " + bgOption);
if (bgOption == "rename_folder") Folders_ShowRenameFolderDialog(FolderNode.id);
if (bgOption == "new_folder") {
let FolderId = Folders_AddNewFolder({ParentId: FolderNode.id});
Folders_ShowRenameFolderDialog(FolderId);
}
if (bgOption == "new_tab") Tabs_OpenNewTab(false, undefined, FolderNode.childNodes[1]);
if (bgOption == "expand_collapse") DOM_EventExpandBox(FolderNode);
if (bgOption == "close_folder") Folders_RemoveFolder(FolderNode.id);
if (bgOption == "unload_folder") {
let tabsArr = [];
let query = document.querySelectorAll("#" + FolderNode.id + " .tab");
for (let s of query) {
tabsArr.push(parseInt(s.id));
}
Tabs_DiscardTabs(tabsArr);
}
}

View File

@ -1,574 +1,394 @@
// 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/
// ********** GROUPS FUNCTIONS ***************
function SaveGroups() {
chrome.runtime.sendMessage({command: "save_groups", groups: tt.groups, windowId: tt.CurrentWindowId});
function Groups_AppendGroupToList(groupId, group_name, font_color, SetEvents) {
if (document.getElementById(groupId) == null) {
let grp = DOM_New("div", document.getElementById("groups"), {id: groupId, className: "group"}, {display: "none"});
DOM_New("div", grp, {id: ("°" + groupId), className: "children"});
if (SetEvents) {
grp.onclick = function(event) {
if (event.which == 1 && event.target == this && event.clientX < (this.childNodes[0].getBoundingClientRect().width + this.getBoundingClientRect().left)) DOM_Deselect();
}
grp.onmousedown = function(event) {
event.stopImmediatePropagation();
if (event.which == 1 && event.target == this && event.clientX < (this.childNodes[0].getBoundingClientRect().width + this.getBoundingClientRect().left)) {
Menu_HideMenus();
return false;
}
if (event.which == 2) {
event.preventDefault();
Groups_ActionClickGroup(this, opt.midclick_group);
}
if (event.which == 3 && event.target.id == this.id) Menu_ShowFGlobalMenu(event);
if (browserId == "V") {
chrome.windows.getCurrent({populate: false}, function(window) {
if (tt.CurrentWindowId != window.id && window.focused) location.reload();
});
}
}
grp.ondragover = function(event) {
if (event.target.id == this.id && (tt.DraggingGroup || tt.DraggingPin || tt.DraggingTab || tt.DraggingFolder)) {
DOM_RemoveHighlight();
this.classList.add("highlighted_drop_target");
}
}
grp.ondblclick = function(event) {
if (event.target.id == this.id) Groups_ActionClickGroup(this, opt.dbclick_group);
}
if (opt.switch_with_scroll) DOM_BindTabsSwitchingToMouseWheel(groupId);
}
}
if (document.getElementById("_" + groupId) == null) {
let gbn = DOM_New("div", document.getElementById("group_list"), {id: ("_" + groupId), className: "group_button", draggable: (SetEvents ? true : false)});
DOM_New("span", gbn, {id: ("_gte" + groupId), className: "group_title", textContent: group_name}, {color: (font_color != "" ? ("#" + font_color) : (window.getComputedStyle(document.getElementById("body"), null).getPropertyValue("--group_list_default_font_color")))});
DOM_New("div", gbn, {id: ("di" + groupId), className: "drag_indicator"});
if (SetEvents) {
gbn.onclick = function(event) {
Groups_SetActiveGroup(this.id.substr(1), true, true);
}
gbn.onmousedown = function(event) {
if (event.which == 3) Menu_ShowFGroupMenu(document.getElementById(this.id.substr(1)), event);
}
gbn.ondblclick = function(event) {
if (event.which == 1 && this.id != "_tab_list") Groups_ShowGroupEditWindow((this.id).substr(1));
}
gbn.ondragstart = function(event) { // DRAG START
event.stopPropagation();
event.dataTransfer.setDragImage(document.getElementById("DragImage"), 0, 0);
event.dataTransfer.setData("text", "");
event.dataTransfer.setData("SourceWindowId", tt.CurrentWindowId);
DOM_CleanUpDragAndDrop();
tt.Dragging = true;
tt.DraggingGroup = true;
tt.DragTreeDepth = -1;
let groupId = this.id.substr(1);
let Group = Object.assign({}, tt.groups[groupId]);
let Nodes = [];
let query = document.querySelectorAll("#" + groupId + " .tab, #" + groupId + " .folder");
for (let s of query) {
if (s.classList.contains("tab")) {
tt.DraggingTab = true;
Nodes.push({id: s.id, parent: s.parentNode.id, selected: false, temporary: false, NodeClass: "tab"});
}
if (s.classList.contains("folder")) {
tt.DraggingFolder = true;
Nodes.push({id: s.id, parent: s.parentNode.id, selected: false, temporary: false, 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 : "")});
}
}
event.dataTransfer.setData("Group", JSON.stringify(Group));
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});
}
gbn.ondragover = function(event) {
if (this.classList.contains("inside") == false && tt.DraggingGroup == false && (tt.DraggingPin || tt.DraggingTab || tt.DraggingFolder)) {
DOM_RemoveHighlight();
DOM_SetClasses(this, ["inside", "highlighted_drop_target"], ["before", "after"], []);
}
if (this.classList.contains("before") == false && event.layerY < this.clientHeight / 2 && tt.DraggingGroup) {
DOM_RemoveHighlight();
DOM_SetClasses(this, ["before", "highlighted_drop_target"], ["inside", "after"], []);
}
if (this.classList.contains("after") == false && event.layerY > this.clientHeight / 2 && tt.DraggingGroup) {
DOM_RemoveHighlight();
DOM_SetClasses(this, ["after", "highlighted_drop_target"], ["inside", "before"], []);
}
}
gbn.ondragenter = function(event) {
if (opt.open_tree_on_hover) {
if (this.classList.contains("active") == false && (tt.DraggingGroup || tt.DraggingPin || tt.DraggingTab || tt.DraggingFolder)) {
clearTimeout(tt.DragOverTimer);
let This = this;
tt.DragOverTimer = setTimeout(function() {Groups_SetActiveGroup(This.id.substr(1), false, false);}, 1500);
}
}
}
DOM_RefreshGUI();
}
}
}
function AppendGroups(Groups) {
if (opt.debug) {
log("f: AppendGroups, Groups: "+JSON.stringify(Groups));
}
AppendGroupToList("tab_list", labels.ungrouped_group, "", true);
for (var group in Groups) {
AppendGroupToList(Groups[group].id, Groups[group].name, Groups[group].font, true);
if (document.querySelectorAll(".group").length == Object.keys(Groups).length) {
RearrangeGroupsButtons();
setTimeout(function() {
RearrangeGroupsLists();
}, 50);
}
}
function Groups_AddNewGroup(Name, FontColor) {
let newId = Groups_GenerateNewGroupID();
tt.groups[newId] = {id: newId, index: 0, active_tab: 0, prev_active_tab: 0, name: (Name ? Name : labels.noname_group), font: (FontColor ? FontColor : "")};
if (opt.debug) Utils_log("f: AddNewGroup, groupId: " + newId + ", Name: " + Name + ", FontColor: " + FontColor);
Groups_AppendGroupToList(newId, tt.groups[newId].name, tt.groups[newId].font, true);
Groups_UpdateBgGroupsOrder();
return newId;
}
function RearrangeGroupsButtons(first_loop) {
if (opt.debug) {
log("f: RearrangeGroupsButtons");
}
document.querySelectorAll(".group_button").forEach(function(s){
let groupId = (s.id).substr(1);
if (tt.groups[groupId]) {
if (s.parentNode.childNodes[tt.groups[groupId].index] != undefined) {
let Ind = Array.from(s.parentNode.children).indexOf(s);
if (Ind > tt.groups[groupId].index) {
InsterBeforeNode(s, s.parentNode.childNodes[tt.groups[groupId].index]);
} else {
InsterAfterNode(s, s.parentNode.childNodes[tt.groups[groupId].index]);
}
let newInd = Array.from(s.parentNode.children).indexOf(s);
if (newInd != tt.groups[groupId].index && first_loop) {
RearrangeGroupsButtons(false);
}
}
}
});
function Groups_SaveGroups() {
chrome.runtime.sendMessage({command: "save_groups", groups: tt.groups, windowId: tt.CurrentWindowId});
}
function RearrangeGroupsLists() {
if (opt.debug) {
log("f: RearrangeGroupsLists");
}
let activegroup = document.getElementById(tt.active_group);
let scroll = activegroup.scrollTop;
let groups = document.getElementById("groups");
document.querySelectorAll(".group_button").forEach(function(s){
let group = document.getElementById((s.id).substr(1));
if (group != null) {
groups.appendChild(group);
}
});
activegroup.scrollTop = scroll;
function Groups_AppendGroups(groups) {
Groups_AppendGroupToList("tab_list", labels.ungrouped_group, "", true);
for (var group in groups) {
Groups_AppendGroupToList(groups[group].id, groups[group].name, groups[group].font, true);
if (document.querySelectorAll(".group").length == Object.keys(groups).length) {
Groups_RearrangeGroupsButtons();
setTimeout(function() {Groups_RearrangeGroupsLists();}, 50);
}
}
}
function AppendGroupToList(groupId, group_name, font_color, SetEvents) {
if (opt.debug) {
log("f: AppendGroupToList, groupId: "+groupId+", group_name: "+group_name+", font_color: "+font_color+", SetEvents: "+SetEvents);
}
if (document.getElementById(groupId) == null) {
let grp = document.createElement("div"); grp.className = "group"; grp.id = groupId; grp.style.display = "none"; document.getElementById("groups").appendChild(grp);
let gcf = document.createElement("div"); gcf.className = "children_folders"; gcf.id = "cf"+groupId; grp.appendChild(gcf);
let gct = document.createElement("div"); gct.className = "children_tabs"; gct.id = "ct"+groupId; grp.appendChild(gct);
if (SetEvents) {
grp.onclick = function(event) {
if (event.which == 1 && event.target == this && event.clientX < (this.childNodes[0].getBoundingClientRect().width + this.getBoundingClientRect().left)) {
DeselectFolders();
DeselectTabs();
}
}
grp.onmousedown = function(event) {
event.stopImmediatePropagation();
if (event.which == 1 && event.target == this && event.clientX < (this.childNodes[0].getBoundingClientRect().width + this.getBoundingClientRect().left)) {
HideMenus();
return false;
}
if (event.which == 2) {
event.preventDefault();
ActionClickGroup(this, opt.midclick_group);
}
if (event.which == 3 && event.target.id == this.id) {
// SHOW MENU
ShowFGlobalMenu(event);
}
if (browserId == "V") {
chrome.windows.getCurrent({populate: false}, function(window) {
if (tt.CurrentWindowId != window.id && window.focused) {
location.reload();
}
});
}
}
grp.ondragover = function(event) {
// PIN,TAB==>GROUP
if (event.target.id == this.id && (tt.DragNodeClass == "tab" || tt.DragNodeClass == "folder")) {
RemoveHighlight();
this.classList.add("highlighted_drop_target");
}
// tt.DragOverId = this.id;
}
// grp.ondragenter = function(event) {
// console.log("clearTimeout");
// if (opt.open_tree_on_hover) {
// clearTimeout(tt.DragOverTimer);
// }
// }
// DOUBLE CLICK ACTION
grp.ondblclick = function(event) {
if (event.target.id == this.id) {
ActionClickGroup(this, opt.dbclick_group);
}
}
if (opt.switch_with_scroll) {
BindTabsSwitchingToMouseWheel(groupId);
}
}
}
if (document.getElementById("_"+groupId) == null) {
let gbn = document.createElement("div"); gbn.className = "group_button"; if (SetEvents) {gbn.draggable = true;} gbn.id = "_"+groupId; document.getElementById("group_list").appendChild(gbn);
let gte = document.createElement("span"); gte.className = "group_title"; gte.id = "_gte"+groupId; gte.textContent = group_name;
if (font_color != "") {
gte.style.color = "#"+font_color;
} else {
gte.style.color = window.getComputedStyle(document.getElementById("body"), null).getPropertyValue("--group_list_default_font_color");
}
gbn.appendChild(gte);
var di = document.createElement("div"); di.className = "drag_indicator"; di.id = "di"+groupId; gbn.appendChild(di); // DROP TARGET INDICATOR
if (SetEvents) {
// ACTIVATE GROUP
gbn.onclick = function(event) {
SetActiveGroup(this.id.substr(1), true, true);
}
// SHOW GROUP MENU
gbn.onmousedown = function(event) {
if (event.which == 3) {
ShowFGroupMenu(document.getElementById(this.id.substr(1)), event);
}
}
// EDIT GROUP
gbn.ondblclick = function(event) {
if (event.which == 1 && this.id != "_tab_list") {
ShowGroupEditWindow((this.id).substr(1));
}
}
// DRAGGING GROUPS
gbn.ondragstart = function(event) { // DRAG START
GroupStartDrag(this, event);
}
gbn.ondragover = function(event) {
GroupButtonDragOver(this, event);
}
gbn.ondragenter = function(event) {
// console.log("gbn.ondragenter");
if (opt.open_tree_on_hover) {
if (this.classList.contains("active") == false && tt.DragNodeClass != "group") {
clearTimeout(tt.DragOverTimer);
let This = this;
tt.DragOverTimer = setTimeout(function() {
SetActiveGroup(This.id.substr(1), false, false);
}, 1500);
}
}
}
// gbn.ondragleave = function(event) {
// console.log("gbn.ondragleave");
// if (opt.open_tree_on_hover) {
// clearTimeout(tt.DragOverTimer);
// }
// }
}
}
RefreshGUI();
function Groups_RearrangeGroupsButtons(first_loop) {
let query = document.querySelectorAll(".group_button");
for (let s of query) {
let groupId = (s.id).substr(1);
if (tt.groups[groupId]) {
if (s.parentNode.childNodes[tt.groups[groupId].index] != undefined) {
let Ind = Array.from(s.parentNode.children).indexOf(s);
if (Ind > tt.groups[groupId].index) {
DOM_InsterBeforeNode(s, s.parentNode.childNodes[tt.groups[groupId].index]);
} else {
DOM_InsterAfterNode(s, s.parentNode.childNodes[tt.groups[groupId].index]);
}
let newInd = Array.from(s.parentNode.children).indexOf(s);
if (newInd != tt.groups[groupId].index && first_loop) Groups_RearrangeGroupsButtons(false);
}
}
}
}
function GenerateNewGroupID(){
let newID = "";
while (newID == "") {
newID = "g_"+GenerateRandomID();
if (document.getElementById(newID) != null) {
newID = "";
}
}
return newID;
function Groups_RearrangeGroupsLists() {
if (opt.debug) Utils_log("f: RearrangeGroupsLists");
let activegroup = document.getElementById(tt.active_group);
let scroll = activegroup.scrollTop;
let groups = document.getElementById("groups");
let query = document.querySelectorAll(".group_button");
for (let s of query) {
let group = document.getElementById((s.id).substr(1));
if (group != null) groups.appendChild(group);
}
activegroup.scrollTop = scroll;
}
function AddNewGroup(Name, FontColor) {
let newId = GenerateNewGroupID();
tt.groups[newId] = { id: newId, index: 0, active_tab: 0, prev_active_tab: 0, active_tab_ttid: "", name: (Name ? Name : labels.noname_group), font: (FontColor ? FontColor : "") };
if (opt.debug) {
log("f: AddNewGroup, groupId: "+newId+", Name: "+Name+", FontColor: "+FontColor);
}
AppendGroupToList(newId, tt.groups[newId].name, tt.groups[newId].font, true);
UpdateBgGroupsOrder();
return newId;
function Groups_UpdateBgGroupsOrder() {
let query = document.querySelectorAll(".group_button");
for (let s of query) {
if (tt.groups[(s.id).substr(1)]) tt.groups[(s.id).substr(1)].index = Array.from(s.parentNode.children).indexOf(s);
}
Groups_SaveGroups();
}
// remove group, delete tabs if close_tabs is true
function GroupRemove(groupId, close_tabs) {
if (close_tabs) {
let tabIds = Array.prototype.map.call(document.querySelectorAll("#"+groupId+" .tab"), function(s){
return parseInt(s.id);
});
CloseTabs(tabIds);
document.querySelectorAll("#"+groupId+" .folder").forEach(function(s){
RemoveFolder(s.id);
});
} else {
let TabListFolders = document.getElementById("cftab_list");
let GroupFolders = document.getElementById("cf"+groupId);
if (GroupFolders != null) {
while (GroupFolders.firstChild) {
TabListFolders.appendChild(GroupFolders.firstChild);
}
}
let TabListTabs = document.getElementById("cttab_list");
let GroupTabs = document.getElementById("ct"+groupId);
if (GroupTabs != null) {
while (GroupTabs.firstChild) {
TabListTabs.appendChild(GroupTabs.firstChild);
}
}
RefreshExpandStates();
RefreshCounters();
}
if (groupId != "tab_list") {
delete tt.groups[groupId];
if (groupId == tt.active_group) {
if (document.getElementById("_"+groupId).previousSibling) {
SetActiveGroup((document.getElementById("_"+groupId).previousSibling.id).substr(1), true, true);
} else {
if (document.getElementById("_"+groupId).nextSibling) {
SetActiveGroup((document.getElementById("_"+groupId).nextSibling.id).substr(1), true, true);
} else {
SetActiveGroup("tab_list", true, true);
}
}
}
let group = document.getElementById(groupId);
if (group != null) {
group.parentNode.removeChild(group);
}
let groupButton = document.getElementById("_"+groupId);
if (groupButton != null) {
groupButton.parentNode.removeChild(groupButton);
}
}
SaveGroups();
tt.schedule_update_data++;
function Groups_GenerateNewGroupID() {
let newID = "";
while (newID == "") {
newID = "g_" + GenerateRandomID();
if (document.getElementById(newID) != null) newID = "";
}
return newID;
}
function UpdateBgGroupsOrder() {
document.querySelectorAll(".group_button").forEach(function(s){
if (tt.groups[(s.id).substr(1)]) {
tt.groups[(s.id).substr(1)].index = Array.from(s.parentNode.children).indexOf(s);
}
});
SaveGroups();
function Groups_GroupRemove(groupId, close_tabs) { // remove group, delete tabs if close_tabs is true
if (close_tabs) {
let tabIds = Array.prototype.map.call(document.querySelectorAll("#" + groupId + " .tab"), function(s) {return parseInt(s.id);});
Tabs_CloseTabs(tabIds);
let query = document.querySelectorAll("#" + groupId + " .folder");
for (let s of query) {
Folders_RemoveFolder(s.id);
}
} else {
let TabList = document.getElementById("°tab_list");
let GroupList = document.getElementById("°" + groupId);
if (TabList != null && GroupList != null) {
while (GroupList.firstChild) {
TabList.appendChild(GroupList.firstChild);
}
}
DOM_RefreshExpandStates();
DOM_RefreshCounters();
}
if (groupId != "tab_list") {
delete tt.groups[groupId];
let active_tab_is_pin = document.querySelector(".pin.active_tab");
if (groupId == tt.active_group && active_tab_is_pin == null) {
if (document.getElementById("_" + groupId).previousSibling) {
Groups_SetActiveGroup((document.getElementById("_" + groupId).previousSibling.id).substr(1), true, true);
} else {
if (document.getElementById("_" + groupId).nextSibling) {
Groups_SetActiveGroup((document.getElementById("_" + groupId).nextSibling.id).substr(1), true, true);
} else {
Groups_SetActiveGroup("tab_list", true, true);
}
}
}
let group = document.getElementById(groupId);
if (group != null) group.parentNode.removeChild(group);
let groupButton = document.getElementById("_" + groupId);
if (groupButton != null) groupButton.parentNode.removeChild(groupButton);
}
Groups_SaveGroups();
tt.schedule_update_data++;
}
function KeepOnlyOneActiveTabInGroup() {
let active_tabs = document.querySelectorAll("#"+tt.active_group+" .active_tab");
if (active_tabs.length > 1) {
chrome.tabs.query({currentWindow: true, active: true}, function(activeTab) {
SetActiveTab(activeTab[0].id, false);
});
}
function Groups_KeepOnlyOneActiveTabInGroup() {
let active_tabs = document.querySelectorAll("#" + tt.active_group + " .active_tab");
if (active_tabs.length > 1) {
chrome.tabs.query({currentWindow: true, active: true}, function(activeTab) {
Tabs_SetActiveTab(activeTab[0].id, false);
});
}
}
function SetActiveGroup(groupId, switch_to_active_in_group, scroll_to_active) {
if (opt.debug) {
log("f: SetActiveGroup, groupId: "+groupId+", switch_to_active_in_group: "+switch_to_active_in_group+", scroll_to_active: "+scroll_to_active);
}
let group = document.getElementById(groupId);
if (group != null) {
tt.active_group = groupId;
document.querySelectorAll(".group_button").forEach(function(s){
s.classList.remove("active_group");
});
document.getElementById("_"+groupId).classList.add("active_group");
document.querySelectorAll(".group").forEach(function(s){
s.style.display = "none";
});
group.style.display = "";
RefreshGUI();
HideRenameDialogs()
let activeTab = document.querySelector("#"+groupId+" .active_tab");
if (activeTab != null ){
if (switch_to_active_in_group){
chrome.tabs.update(parseInt(activeTab.id), {active: true});
}
if (scroll_to_active){
ScrollToTab(activeTab.id);
}
KeepOnlyOneActiveTabInGroup();
}
if (groupId == "tab_list") {
document.querySelectorAll("#button_remove_group, #button_edit_group").forEach(function(s){
s.classList.add("disabled");
});
} else {
document.querySelectorAll("#button_remove_group, #button_edit_group").forEach(function(s){
s.classList.remove("disabled");
});
}
chrome.runtime.sendMessage({command: "set_active_group", active_group: groupId, windowId: tt.CurrentWindowId});
RefreshExpandStates();
RefreshCounters();
if (browserId == "F" && opt.hide_other_groups_tabs_firefox) {
let HideTabIds = Array.prototype.map.call(document.querySelectorAll(".group:not([id='"+groupId+"']) .tab"), function(s){
return parseInt(s.id);
});
let ShowTabIds = Array.prototype.map.call(document.querySelectorAll("#"+groupId+" .tab"), function(s){
return parseInt(s.id);
});
browser.tabs.hide(HideTabIds);
browser.tabs.show(ShowTabIds);
}
}
function Groups_SetActiveGroup(groupId, switch_to_active_in_group, scroll_to_active) {
if (opt.debug) Utils_log("f: SetActiveGroup, groupId: " + groupId + ", switch_to_active_in_group: " + switch_to_active_in_group + ", scroll_to_active: " + scroll_to_active);
let group = document.getElementById(groupId);
if (group != null) {
tt.active_group = groupId;
let query = document.querySelectorAll(".group_button");
for (let s of query) {
s.classList.remove("active_group");
}
document.getElementById("_" + groupId).classList.add("active_group");
query = document.querySelectorAll(".group");
for (let s of query) {
s.style.display = "none";
}
group.style.display = "";
DOM_RefreshGUI();
DOM_HideRenameDialogs()
let activeTab = document.querySelector("#" + groupId + " .active_tab");
if (activeTab != null) {
if (switch_to_active_in_group) chrome.tabs.update(parseInt(activeTab.id), {active: true});
if (scroll_to_active && tt.tabs[activeTab.id]) tt.tabs[activeTab.id].ScrollToTab();
Groups_KeepOnlyOneActiveTabInGroup();
}
if (groupId == "tab_list") {
let query = document.querySelectorAll("#button_remove_group, #button_edit_group");
for (let s of query) {
s.classList.add("disabled");
}
} else {
let query = document.querySelectorAll("#button_remove_group, #button_edit_group");
for (let s of query) {
s.classList.remove("disabled");
}
}
chrome.runtime.sendMessage({command: "set_active_group", active_group: groupId, windowId: tt.CurrentWindowId});
DOM_RefreshExpandStates();
DOM_RefreshCounters();
if (browserId == "F" && opt.hide_other_groups_tabs_firefox) {
let HideTabIds = Array.prototype.map.call(document.querySelectorAll(".group:not([id='" + groupId + "']) .tab"), function(s) {
return parseInt(s.id);
});
let ShowTabIds = Array.prototype.map.call(document.querySelectorAll("#" + groupId + " .tab"), function(s) {
return parseInt(s.id);
});
browser.tabs.hide(HideTabIds);
browser.tabs.show(ShowTabIds);
}
}
}
function SetActiveTabInGroup(groupId, tabId) {
if (document.querySelector("#"+groupId+" [id='"+tabId+"']") != null && tt.groups[groupId] != undefined) {
if (groupId != tt.active_group) {
SetActiveGroup(groupId, false, true);
}
if (tt.groups[groupId]) {
tt.groups[groupId].prev_active_tab = tt.groups[groupId].active_tab;
tt.groups[groupId].active_tab = parseInt(tabId);
}
SaveGroups();
}
function Groups_SetActiveTabInGroup(groupId, tabId) {
if (document.querySelector("#" + groupId + " [id='" + tabId + "']") != null && tt.groups[groupId] != undefined) {
if (groupId != tt.active_group) Groups_SetActiveGroup(groupId, false, true);
if (tt.groups[groupId]) {
tt.groups[groupId].prev_active_tab = tt.groups[groupId].active_tab;
tt.groups[groupId].active_tab = parseInt(tabId);
}
Groups_SaveGroups();
}
}
// Edit group popup
function ShowGroupEditWindow(groupId) {
HideRenameDialogs();
if (tt.groups[groupId]) {
let name = document.getElementById("group_edit_name");
name.value = tt.groups[groupId].name;
let groupEditDialog = document.getElementById("group_edit");
groupEditDialog.setAttribute("groupId", groupId);
groupEditDialog.style.display = "block";
groupEditDialog.style.top = document.getElementById("toolbar").getBoundingClientRect().height + document.getElementById("pin_list").getBoundingClientRect().height + 8 + "px";
// groupEditDialog.style.left = "22px";
groupEditDialog.style.left = "";
let DefaultGroupButtonFontColor = window.getComputedStyle(document.getElementById("body"), null).getPropertyValue("--group_list_default_font_color");
let GroupEditFont = document.getElementById("group_edit_font");
GroupEditFont.style.backgroundColor = (tt.groups[groupId].font == "" ? DefaultGroupButtonFontColor : "#"+tt.groups[groupId].font);
setTimeout(function(){
document.getElementById("group_edit_name").select();
},5);
}
function Groups_ShowGroupEditWindow(groupId) { // Edit group popup
DOM_HideRenameDialogs();
if (tt.groups[groupId]) {
let name = document.getElementById("group_edit_name");
name.value = tt.groups[groupId].name;
let groupEditDialog = document.getElementById("group_edit");
groupEditDialog.setAttribute("groupId", groupId);
DOM_SetStyle(groupEditDialog, {display: "block", left: "", top: document.getElementById("toolbar").getBoundingClientRect().height + document.getElementById("pin_list").getBoundingClientRect().height + 8 + "px"});
let DefaultGroupButtonFontColor = window.getComputedStyle(document.getElementById("body"), null).getPropertyValue("--group_list_default_font_color");
let GroupEditFont = document.getElementById("group_edit_font");
GroupEditFont.style.backgroundColor = (tt.groups[groupId].font == "" ? DefaultGroupButtonFontColor : "#" + tt.groups[groupId].font);
setTimeout(function() {document.getElementById("group_edit_name").select();}, 5);
}
}
// when pressed OK in group popup
function GroupEditConfirm() {
let groupId = document.getElementById("group_edit").getAttribute("groupId");
if (tt.groups[groupId]) {
let GroupEditName = document.getElementById("group_edit_name");
// GroupEditName.value = GroupEditName.value.replace(/[\f\n\r\v\t\<\>\+\-\(\)\.\,\;\:\~\/\|\?\@\!\"\'\£\$\%\&\^\#\=\*\[\]]?/gi, "");
tt.groups[groupId].name = GroupEditName.value;
let GroupEditFont = document.getElementById("group_edit_font");
let DefaultGroupButtonFontColor = window.getComputedStyle(document.getElementById("body"), null).getPropertyValue("--group_list_default_font_color");
let ThisGroupButtonFontColor = RGBtoHex(GroupEditFont.style.backgroundColor);
if ("#"+ThisGroupButtonFontColor != DefaultGroupButtonFontColor) {
tt.groups[groupId].font = ThisGroupButtonFontColor;
document.getElementById("_gte"+groupId).style.color = "#"+ThisGroupButtonFontColor;
}
HideRenameDialogs();
RefreshGUI();
SaveGroups();
}
function Groups_GroupEditConfirm() { // when pressed OK in group popup
let groupId = document.getElementById("group_edit").getAttribute("groupId");
if (tt.groups[groupId]) {
let GroupEditName = document.getElementById("group_edit_name");
tt.groups[groupId].name = GroupEditName.value;
let GroupEditFont = document.getElementById("group_edit_font");
let DefaultGroupButtonFontColor = window.getComputedStyle(document.getElementById("body"), null).getPropertyValue("--group_list_default_font_color");
let ThisGroupButtonFontColor = Utils_RGBtoHex(GroupEditFont.style.backgroundColor);
if ("#" + ThisGroupButtonFontColor != DefaultGroupButtonFontColor) {
tt.groups[groupId].font = ThisGroupButtonFontColor;
document.getElementById("_gte" + groupId).style.color = "#" + ThisGroupButtonFontColor;
}
DOM_HideRenameDialogs();
DOM_RefreshGUI();
Groups_SaveGroups();
}
}
function RestoreStateOfGroupsToolbar() {
chrome.runtime.sendMessage({command: "get_group_bar", windowId: tt.CurrentWindowId}, function(response) {
let toolbarGroups = document.getElementById("toolbar_groups");
if (response == true) {
toolbarGroups.style.display = "inline-block";
toolbarGroups.style.width = "19px";
toolbarGroups.style.borderRight = "1px solid var(--group_list_borders)";
toolbarGroups.classList.remove("hidden");
} else {
toolbarGroups.style.display = "none";
toolbarGroups.style.width = "0px";
toolbarGroups.style.borderRight = "none";
toolbarGroups.classList.add("hidden");
}
});
function Groups_RestoreStateOfGroupsToolbar() {
chrome.runtime.sendMessage({command: "get_group_bar", windowId: tt.CurrentWindowId}, function(response) {
let toolbarGroups = document.getElementById("toolbar_groups");
if (response == true) {
DOM_SetStyle(toolbarGroups, {display: "inline-block", width: "19px", borderRight: "1px solid var(--group_list_borders)"});
toolbarGroups.classList.remove("hidden");
} else {
DOM_SetStyle(toolbarGroups, {display: "none", width: "0px", borderRight: "none"});
toolbarGroups.classList.add("hidden");
}
});
}
function GroupsToolbarToggle() {
let toolbarGroups = document.getElementById("toolbar_groups");
toolbarGroups.classList.toggle("hidden");
if (toolbarGroups.classList.contains("hidden")) {
toolbarGroups.style.display = "none";
toolbarGroups.style.width = "0px";
toolbarGroups.style.borderRight = "none";
chrome.runtime.sendMessage({command: "set_group_bar", group_bar: false, windowId: tt.CurrentWindowId});
} else {
toolbarGroups.style.display = "inline-block";
toolbarGroups.style.width = "19px";
toolbarGroups.style.borderRight = "1px solid var(--group_list_borders)";
chrome.runtime.sendMessage({command: "set_group_bar", group_bar: true, windowId: tt.CurrentWindowId});
}
RefreshGUI();
function Groups_GroupsToolbarToggle() {
let toolbarGroups = document.getElementById("toolbar_groups");
toolbarGroups.classList.toggle("hidden");
if (toolbarGroups.classList.contains("hidden")) {
DOM_SetStyle(toolbarGroups, {display: "none", width: "0px", borderRight: "none"});
chrome.runtime.sendMessage({command: "set_group_bar", group_bar: false, windowId: tt.CurrentWindowId});
} else {
DOM_SetStyle(toolbarGroups, {display: "inline-block", width: "19px", borderRight: "1px solid var(--group_list_borders)"});
chrome.runtime.sendMessage({command: "set_group_bar", group_bar: true, windowId: tt.CurrentWindowId});
}
DOM_RefreshGUI();
}
function ActionClickGroup(Node, bgOption) {
if (bgOption == "new_tab") {
if (Node.id == "pin_list") {
OpenNewTab(true, undefined);
}
if (Node.classList.contains("tab") || Node.classList.contains("folder") || Node.classList.contains("group")) {
OpenNewTab(false, Node.id);
}
}
if (bgOption == "activate_previous_active") {
chrome.tabs.update(parseInt(tt.groups[tt.active_group].prev_active_tab), {active: true});
}
if (bgOption == "undo_close_tab") {
chrome.sessions.getRecentlyClosed( null, function(sessions) {
if (sessions.length > 0) {
chrome.sessions.restore(null, function(restored) {});
}
});
}
function Groups_ActionClickGroup(Node, bgOption) {
if (bgOption == "new_tab") {
if (Node.id == "pin_list") Tabs_OpenNewTab(true, undefined, undefined);
if (Node.classList.contains("tab")) Tabs_OpenNewTab(false, Node);
if (Node.classList.contains("folder")) Tabs_OpenNewTab(false, undefined, Node.childNodes[1]);
if (Node.classList.contains("group")) Tabs_OpenNewTab(false, undefined, Node.childNodes[0]);
}
if (bgOption == "activate_previous_active") {
chrome.tabs.update(parseInt(tt.groups[tt.active_group].prev_active_tab), {active: true});
}
if (bgOption == "undo_close_tab") {
chrome.sessions.getRecentlyClosed(null, function(sessions) {
if (sessions.length > 0) chrome.sessions.restore(null, function(restored) {});
});
}
}
// SET ACTIVE TAB FOR EACH GROUP
function SetActiveTabInEachGroup() {
chrome.tabs.query({currentWindow: true, active: true}, function(tabs) {
if (tabs.length) {
SetActiveTab(tabs[0].id);
chrome.runtime.sendMessage({command: "get_active_group", windowId: tt.CurrentWindowId}, function(response) {
if (response) {
SetActiveGroup(response, false, true);
for (var group in tt.groups) {
let ActiveInGroup = document.querySelector("#"+group+" [id='"+tt.groups[group].active_tab+"']");
if (ActiveInGroup != null) {
ActiveInGroup.classList.add("active_tab");
}
}
if (tabs[0].pinned) {
let ActiveTabinActiveGroup = document.querySelectorAll("#"+tt.active_group+" .active_tab");
if (ActiveTabinActiveGroup != null) {
ActiveTabinActiveGroup.forEach(function(s){
s.classList.remove("active_tab");
});
}
}
} else {
SetActiveGroup("tab_list", false, true);
}
});
}
});
}
// function ActionClickGroup(GroupNode, bgOption) {
// if (opt.debug) {
// log("f: ActionClickGroup, GroupId "+GroupNode.id+", bgOption: "+bgOption);
// }
// if (bgOption == "rename_folder") {
// ShowRenameFolderDialog(FolderNode.id);
// }
// }
function GroupButtonDragOver(Node, event) {
if (Node.classList.contains("inside") == false && (tt.DragNodeClass == "tab" || tt.DragNodeClass == "folder")) {
RemoveHighlight();
Node.classList.remove("before");
Node.classList.remove("after");
Node.classList.add("inside");
Node.classList.add("highlighted_drop_target");
}
if (Node.classList.contains("before") == false && event.layerY < Node.clientHeight/2 && tt.DragNodeClass == "group") {
RemoveHighlight();
Node.classList.add("before");
Node.classList.remove("after");
Node.classList.remove("inside");
Node.classList.add("highlighted_drop_target");
}
if (Node.classList.contains("after") == false && event.layerY > Node.clientHeight/2 && tt.DragNodeClass == "group") {
RemoveHighlight();
Node.classList.remove("before");
Node.classList.add("after");
Node.classList.remove("inside");
Node.classList.add("highlighted_drop_target");
}
}
function GroupStartDrag(Node, event) {
if (opt.debug) {
log("f: GroupStartDrag, GroupId "+Node.id);
}
event.stopPropagation();
event.dataTransfer.setDragImage(document.getElementById("DragImage"), 0, 0);
event.dataTransfer.setData("text", "");
event.dataTransfer.setData("SourceWindowId", tt.CurrentWindowId);
CleanUpDragClasses();
EmptyDragAndDrop();
tt.DragNodeClass = "group";
let Group = Object.assign({}, tt.groups[Node.id.substr(1)]);
let TabsIds = [];
let TabsIdsParents = [];
let Folders = {};
document.querySelectorAll("#"+Node.id.substr(1)+" .tab").forEach(function(s){
TabsIds.push(parseInt(s.id));
TabsIdsParents.push(s.parentNode.id);
});
document.querySelectorAll("#"+Node.id.substr(1)+" .folder").forEach(function(s){
Folders[s.id] = Object.assign({}, tt.folders[s.id]);
});
// console.log(Group);
// console.log(TabsIds);
// console.log(TabsIdsParents);
// console.log(Folders);
// let Group = document.getElementById(Node.id.substr(1));
event.dataTransfer.setData("Class", "group");
event.dataTransfer.setData("Group", JSON.stringify(Group));
event.dataTransfer.setData("TabsIds", JSON.stringify(TabsIds));
event.dataTransfer.setData("TabsIdsParents", JSON.stringify(TabsIdsParents));
event.dataTransfer.setData("Folders", JSON.stringify(Folders));
chrome.runtime.sendMessage({
command: "drag_drop",
DragNodeClass: "group",
DragTreeDepth: 0
});
}
function Groups_SetActiveTabInEachGroup() { // SET ACTIVE TAB FOR EACH GROUP
chrome.tabs.query({currentWindow: true, active: true}, function(tabs) {
if (tabs.length) {
Tabs_SetActiveTab(tabs[0].id);
chrome.runtime.sendMessage({command: "get_active_group", windowId: tt.CurrentWindowId}, function(response) {
if (response) {
Groups_SetActiveGroup(response, false, true);
for (var group in tt.groups) {
let ActiveInGroup = document.querySelector("#" + group + " [id='" + tt.groups[group].active_tab + "']");
if (ActiveInGroup != null) ActiveInGroup.classList.add("active_tab");
}
if (tabs[0].pinned) {
let ActiveTabinActiveGroup = document.querySelectorAll("#" + tt.active_group + " .active_tab");
if (ActiveTabinActiveGroup != null) {
for (let s of ActiveTabinActiveGroup) {
s.classList.remove("active_tab");
}
}
}
} else {
Groups_SetActiveGroup("tab_list", false, true);
}
});
}
});
}

View File

@ -1,313 +0,0 @@
// 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/
function StartSidebarListeners() {
if (browserId == "F") {
browser.browserAction.onClicked.addListener(function(tab) {
if (tab.windowId == tt.CurrentWindowId) {
browser.sidebarAction.close();
}
});
}
chrome.commands.onCommand.addListener(function(command) {
chrome.windows.getCurrent({populate: false}, function(window) {
if (window.id == tt.CurrentWindowId && window.focused) {
chrome.tabs.query({windowId: tt.CurrentWindowId, active: true}, function(tabs) {
let tabsArr = [];
document.querySelectorAll("[id='"+tabs[0].id+"'] .tab, [id='"+tabs[0].id+"']").forEach(function(s){
tabsArr.push(parseInt(s.id));
if (s.childNodes[1].childNodes.length > 0) {
document.querySelectorAll("#"+s.childNodes[1].id+" .tab").forEach(function(t){
tabsArr.push(parseInt(t.id));
});
}
});
CloseTabs(tabsArr);
});
}
});
});
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if (message.command == "backup_available") {
if (opt.debug) {
log("message to sidebar "+tt.CurrentWindowId+": message: "+message.command);
}
let BAKbutton = document.getElementById("button_load_bak"+message.bak);
if (BAKbutton != null) {
BAKbutton.classList.remove("disabled");
}
return;
}
if (message.command == "drag_drop") {
if (opt.debug) {
log("message to sidebar "+tt.CurrentWindowId+": message: "+message.command);
}
CleanUpDragClasses();
tt.DragNodeClass = message.DragNodeClass;
tt.DragTreeDepth = message.DragTreeDepth;
return;
}
if (message.command == "dragend") {
if (opt.debug) {
log("message to sidebar "+tt.CurrentWindowId+": message: "+message.command);
}
CleanUpDragClasses();
EmptyDragAndDrop();
return;
}
if (message.command == "remove_folder") {
if (opt.debug) {
log("message to sidebar "+tt.CurrentWindowId+": message: "+message.command+" folderId: "+message.folderId);
}
RemoveFolder(message.folderId);
return;
}
if (message.command == "remove_group") {
if (opt.debug) {
log("message to sidebar "+tt.CurrentWindowId+": message: "+message.command+" groupId: "+message.groupId);
}
setTimeout(function() {
GroupRemove(message.groupId, false);
}, 2000);
return;
}
if (message.command == "reload_sidebar") {
if (opt.debug) {
log("message to sidebar "+tt.CurrentWindowId+": message: "+message.command);
}
window.location.reload();
return;
}
if (message.command == "reload_options") {
if (opt.debug) {
log("message to sidebar "+tt.CurrentWindowId+": message: "+message.command);
}
opt = Object.assign({}, message.opt);
setTimeout(function() {
RestorePinListRowSettings();
}, 100);
return;
}
if (message.command == "reload_toolbar") {
if (opt.debug) {
log("message to sidebar "+tt.CurrentWindowId+": message: "+message.command);
}
opt = Object.assign({}, message.opt);
if (opt.show_toolbar) {
RemoveToolbar();
RecreateToolbar(message.toolbar);
SetToolbarEvents(false, true, true, "mousedown");
RestoreToolbarShelf();
RestoreToolbarSearchFilter();
} else {
RemoveToolbar();
}
RefreshGUI();
return;
}
if (message.command == "reload_theme") {
if (opt.debug) {
log("message to sidebar "+tt.CurrentWindowId+": message: "+message.command);
}
RestorePinListRowSettings();
ApplyTheme(message.theme);
return;
}
if (message.windowId == tt.CurrentWindowId) {
if (message.command == "append_group") {
if (tt.groups[message.groupId] == undefined) {
tt.groups[message.groupId] = {id: message.groupId, index: Object.keys(tt.groups).length, active_tab: 0, prev_active_tab: 0, active_tab_ttid: "", name: message.group_name, font: message.font_color};
AppendGroupToList(message.groupId, message.group_name, message.font_color, true);
}
return;
}
if (message.command == "append_tab_to_group") {
let Group = document.getElementById("ct"+message.groupId);
let Tab = document.getElementById(message.tabId);
if (Group && Tab) {
Group.appendChild(Tab);
SetActiveGroup(message.groupId, false, true);
}
return;
}
if (message.command == "tab_created") {
if (message.InsertAfterId && document.querySelectorAll("#"+tt.active_group+" .tab").length == 0) {
message.InsertAfterId = undefined;
message.ParentId = tt.active_group;
}
AppendTab({tab: message.tab, ParentId: message.ParentId, InsertAfterId: message.InsertAfterId, Append: message.Append, Scroll: true});
RefreshExpandStates();
setTimeout(function() {
RefreshCounters();
RefreshGUI();
},50);
if (opt.syncro_tabbar_tabs_order) {
let tabIds = Array.prototype.map.call(document.querySelectorAll(".pin, .tab"), function(s){
return parseInt(s.id);
});
chrome.tabs.move(message.tab.id, {index: tabIds.indexOf(message.tab.id)});
}
setTimeout(function() {
tt.schedule_update_data++;
}, 1000);
return;
}
if (message.command == "tab_attached") {
if (opt.debug) {
log("chrome event: "+message.command+", tabId: "+message.tabId+", tab is pinned: "+message.tab.pinned+", ParentId: "+message.ParentId);
}
AppendTab({tab: message.tab, ParentId: message.ParentId, Append: true, SkipSetActive: true, SkipMediaIcon: true});
RefreshGUI();
return;
}
if (message.command == "tab_detached") {
if (opt.debug) {
log("chrome event: "+message.command+ ", tabId: " + message.tabId);
}
let Tab = document.getElementById(message.tabId);
if (Tab != null) {
let ctDetachedParent = Tab.childNodes[1];
if (opt.promote_children_in_first_child == true && ctDetachedParent.childNodes.length > 1) {
let ctNewParent = document.getElementById(ctDetachedParent.firstChild.id).childNodes[1];
ctDetachedParent.parentNode.parentNode.insertBefore(ctDetachedParent.firstChild, ctDetachedParent.parentNode);
while (ctDetachedParent.firstChild) {
ctNewParent.appendChild(ctDetachedParent.firstChild);
}
} else {
while (ctDetachedParent.firstChild) {
ctDetachedParent.parentNode.parentNode.insertBefore(ctDetachedParent.firstChild, ctDetachedParent.parentNode);
}
}
}
RemoveTabFromList(message.tabId);
setTimeout(function() {
tt.schedule_update_data++;
}, 300);
RefreshGUI();
return;
}
if (message.command == "tab_removed") {
if (opt.debug) {
log("chrome event: "+message.command+ ", tabId: " + message.tabId);
}
let mTab = document.getElementById(message.tabId);
if (mTab != null) {
let ctParent = mTab.childNodes[1];
if (opt.debug) {
log("tab_removed, promote children: " +opt.promote_children);
}
if (opt.promote_children == true) {
if (opt.promote_children_in_first_child == true && ctParent.childNodes.length > 1) {
let ctNewParent = document.getElementById(ctParent.firstChild.id).childNodes[1];
ctParent.parentNode.parentNode.insertBefore(ctParent.firstChild, ctParent.parentNode);
while (ctParent.firstChild) {
ctNewParent.appendChild(ctParent.firstChild);
}
} else {
while (ctParent.firstChild) {
ctParent.parentNode.parentNode.insertBefore(ctParent.firstChild, ctParent.parentNode);
}
}
} else {
document.querySelectorAll("[id='"+message.tabId+"'] .tab").forEach(function(s) {
chrome.tabs.remove(parseInt(s.id));
});
}
RemoveTabFromList(message.tabId);
RefreshExpandStates();
setTimeout(function() {
tt.schedule_update_data++;
}, 300);
RefreshGUI();
RefreshCounters();
}
return;
}
if (message.command == "tab_activated") {
if (opt.debug) {
log("chrome event: "+message.command+ ", tabId: " + message.tabId);
}
SetActiveTab(message.tabId, true);
return;
}
if (message.command == "tab_attention") {
if (opt.debug) {
log("chrome event: "+message.command+ ", tabId: " + message.tabId);
}
SetAttentionIcon(message.tabId);
return;
}
if (message.command == "tab_updated") {
if (opt.debug) {
log("chrome event: "+message.command+ ", tabId: " + message.tabId);
// + ", changeInfo: "+JSON.stringify(message.changeInfo));
// log(message.changeInfo);
}
if (message.changeInfo.favIconUrl != undefined || message.changeInfo.url != undefined) {
setTimeout(function() {
GetFaviconAndTitle(message.tabId, true);
}, 100);
}
if (message.changeInfo.title != undefined) {
setTimeout(function() {
GetFaviconAndTitle(message.tabId, true);
}, 1000);
}
if (message.changeInfo.audible != undefined || message.changeInfo.mutedInfo != undefined) {
RefreshMediaIcon(message.tabId);
}
if (message.changeInfo.discarded != undefined) {
RefreshDiscarded(message.tabId);
// RefreshMediaIcon(message.tabId);
}
if (message.changeInfo.pinned != undefined) {
let updateTab = document.getElementById(message.tabId);
if (updateTab != null) {
if (message.tab.pinned && updateTab.classList.contains("pin") == false) {
SetTabClass(message.tabId, true);
tt.schedule_update_data++;
}
if (!message.tab.pinned && updateTab.classList.contains("tab") == false) {
SetTabClass(message.tabId, false);
tt.schedule_update_data++;
}
}
RefreshExpandStates();
}
return;
}
// if (message.command == "set_active_group") {
// SetActiveGroup(message.groupId, false, false);
// return;
// }
if (message.command == "remote_update") {
if (opt.debug) {
log("chrome event: "+message.command+ ", tabId: " + message.tabId);
log(message);
}
RcreateTreeStructure(message.groups, message.folders, message.tabs);
sendResponse(true);
tt.schedule_update_data++;
return;
}
}
});
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

26
scripts/preferences.js Normal file
View File

@ -0,0 +1,26 @@
function Preferences_SavePreferences(options) {
chrome.storage.local.set({preferences: options});
chrome.runtime.sendMessage({command: "reload_options", opt: options});
}
function Preferences_LoadDefaultPreferences() {
opt = Object.assign({}, DefaultPreferences);
}
function Preferences_GetCurrentPreferences(storage) {
opt = Object.assign({}, DefaultPreferences);
if (storage.preferences) {
for (let parameter in storage["preferences"]) {
if (opt[parameter] != undefined) {
opt[parameter] = storage["preferences"][parameter];
// legacy, changed from "after_active" to "after", because it is a parent tab, not necessarily an active tab
if (parameter == "append_child_tab" && storage["preferences"][parameter] == "after_active") {
opt[parameter] = "after";
}
}
}
} else {
Preferences_SavePreferences(opt);
}
}

View File

@ -1,327 +0,0 @@
// 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/
// ********** REFRESH GUI ***************
async function RefreshGUI() {
let toolbar = document.getElementById("toolbar");
let toolbarHeight = 27;
if (toolbar.children.length > 0) {
toolbar.style.height = "";
toolbar.style.width = "";
toolbar.style.display = "";
toolbar.style.border = "";
toolbar.style.padding = "";
if (document.querySelector(".on.button") != null) {
toolbar.style.height = "53px";
toolbarHeight = 54;
} else {
toolbar.style.height = "26px";
}
} else {
toolbar.style.height = "0px";
toolbarHeight = 0;
toolbar.style.width = "0px";
toolbar.style.display = "none";
toolbar.style.border = "none";
toolbar.style.padding = "0";
}
let group_list = document.getElementById("group_list");
group_list.style.width = document.body.clientWidth + 50 + "px";
let pin_list = document.getElementById("pin_list");
if (pin_list.children.length > 0) {
pin_list.style.top = toolbarHeight + "px";
pin_list.style.height = "";
pin_list.style.width = "";
pin_list.style.display = "";
pin_list.style.border = "";
pin_list.style.padding = "";
} else {
pin_list.style.top = "0px";
pin_list.style.height = "0px";
pin_list.style.width = "0px";
pin_list.style.display = "none";
pin_list.style.border = "none";
pin_list.style.padding = "0";
}
let pin_listHeight = pin_list.getBoundingClientRect().height;
let toolbar_groups = document.getElementById("toolbar_groups");
toolbar_groups.style.top = toolbarHeight + pin_listHeight + "px";
toolbar_groups.style.height = document.body.clientHeight - toolbarHeight - pin_listHeight + "px";
let toolbar_groupsWidth = toolbar_groups.getBoundingClientRect().width;
if (opt.show_counter_groups) {
document.querySelectorAll(".group").forEach(function(s){
let groupLabel = document.getElementById("_gte"+s.id);
if (groupLabel) {
groupLabel.textContent = (tt.groups[s.id] ? tt.groups[s.id].name : labels.noname_group) + " (" + document.querySelectorAll("#"+s.id+" .tab").length + ")";
}
});
} else {
document.querySelectorAll(".group").forEach(function(s){
let groupLabel = document.getElementById("_gte"+s.id);
if (groupLabel) {
groupLabel.textContent = tt.groups[s.id] ? tt.groups[s.id].name : labels.noname_group;
}
});
}
document.querySelectorAll(".group_button").forEach(function(s){
s.style.height = s.firstChild.getBoundingClientRect().height + "px";
});
let groups = document.getElementById("groups");
let groupsHeight = document.body.clientHeight - toolbarHeight - pin_listHeight;
let groupsWidth = document.body.clientWidth - toolbar_groupsWidth - 1;
groups.style.top = toolbarHeight + pin_listHeight + "px";
groups.style.left = toolbar_groupsWidth + "px";
groups.style.height = groupsHeight + "px";
groups.style.width = groupsWidth + "px";
// let bottom_floating_buttons = document.getElementById("status_bar");
// let active_group_tabs = document.getElementById("ct"+tt.active_group);
// bottom_floating_buttons.style.left = toolbar_groupsWidth + "px";
// bottom_floating_buttons.style.width = toolbar_groupsWidth + active_group_tabs.clientWidth + "px";
let PanelList = document.querySelector(".mw_pan_on>.manager_window_list");
let PanelListHeight = 3 + PanelList.children.length * 18;
let ManagerWindowPanelButtons = document.querySelector(".mw_pan_on>.manager_window_panel_buttons");
let ManagerWindowPanelButtonsHeight = ManagerWindowPanelButtons.clientHeight;
let MaxAllowedHeight = document.body.clientHeight - 140;
if (PanelListHeight + ManagerWindowPanelButtonsHeight < MaxAllowedHeight) {
PanelList.style.height = PanelListHeight + "px";
} else {
PanelList.style.height = MaxAllowedHeight - ManagerWindowPanelButtonsHeight + "px";
}
let ManagerWindow = document.getElementById("manager_window");
ManagerWindow.style.height = PanelList.clientHeight + ManagerWindowPanelButtonsHeight + 56 + "px";
}
// set discarded class
function RefreshDiscarded(tabId) {
let t = document.getElementById(tabId);
if (t != null) {
chrome.tabs.get(parseInt(tabId), function(tab) {
if (tab) {
if (tab.discarded) {
t.classList.add("discarded");
} else {
t.classList.remove("discarded");
t.classList.remove("audible");
t.classList.remove("muted");
}
}
});
}
}
// set discarded class
function SetAttentionIcon(tabId) {
let t = document.getElementById(tabId);
if (t != null) {
t.classList.add("attention");
}
}
// change media icon
function RefreshMediaIcon(tabId) {
let t = document.getElementById(tabId);
if (t != null) {
chrome.tabs.get(parseInt(tabId), function(tab) {
if (tab) {
if (tab.mutedInfo.muted && !tab.discarded) {
t.classList.remove("audible");
t.classList.add("muted");
}
if (!tab.mutedInfo.muted && tab.audible && !tab.discarded) {
t.classList.remove("muted");
t.classList.add("audible");
}
if ((!tab.mutedInfo.muted && !tab.audible) || tab.discarded) {
t.classList.remove("audible");
t.classList.remove("muted");
}
}
});
}
}
// Vivaldi does not have changeInfo.audible listener, this is my own implementation, hopefully this will not affect performance too much
function VivaldiRefreshMediaIcons() {
setInterval(function() {
chrome.tabs.query({currentWindow: true, audible: true}, function(tabs) {
document.querySelectorAll(".audible, .muted").forEach(function(s){
s.classList.remove("audible");
s.classList.remove("muted");
});
let tc = tabs.length;
for (var ti = 0; ti < tc; ti++) {
if (tabs[ti].audible) {
document.getElementById(tabs[ti].id).classList.add("audible");
}
if (tabs[ti].mutedInfo.muted) {
document.getElementById(tabs[ti].id).classList.add("muted");
}
}
});
}, 2000);
}
async function LoadFavicon(tabId, Img, TryUrls, TabHeaderNode, i) {
if (TabHeaderNode){
Img.src = TryUrls[i];
Img.onload = function() {
TabHeaderNode.style.backgroundImage = "url(" + TryUrls[i] + ")";
if (browserId == "F") { // cache Firefox favicon - solution for bug with empty favicons in unloaded tabs
browser.sessions.setTabValue(tabId, "CachedFaviconUrl", TryUrls[i]);
}
};
Img.onerror = function() {
if (i < TryUrls.length) {
LoadFavicon(tabId, Img, TryUrls, TabHeaderNode, (i+1));
}
}
}
}
async function GetFaviconAndTitle(tabId, addCounter) {
let t = document.getElementById(tabId);
if (t != null) {
let CachedFavicon;
if (browserId == "F") {
let ttf = Promise.resolve(browser.sessions.getTabValue(tabId, "CachedFaviconUrl")).then(function(FaviconUrl) {
CachedFavicon = FaviconUrl;
});
}
chrome.tabs.get(parseInt(tabId), function(tab) {
if (tab){
let title = tab.title ? tab.title : tab.url;
let tHeader = t.childNodes[0];
let tTitle = t.childNodes[0].childNodes[2];
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();
if (browserId != "F") {
CachedFavicon = "chrome://favicon/"+tab.url;
}
let TryCases = [tab.favIconUrl, CachedFavicon, , "./theme/icon_empty.svg"];
LoadFavicon(tabId, 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) GetFaviconAndTitle(tab.id, addCounter);
}, 1000);
}
if (addCounter && (opt.show_counter_tabs || opt.show_counter_tabs_hints)) {
RefreshTabCounter(tabId);
}
}
});
}
}
// refresh open closed trees states
async function RefreshExpandStates() {
document.querySelectorAll("#"+tt.active_group+" .folder").forEach(function(s){
if (s.childNodes[1].children.length == 0 && s.childNodes[2].children.length == 0) {
s.classList.remove("o");
s.classList.remove("c");
} else {
if (s.classList.contains("o") == false && s.classList.contains("c") == false) {
s.classList.add("o");
}
}
});
document.querySelectorAll("#"+tt.active_group+" .tab").forEach(function(s){
if (s.childNodes[1].children.length == 0) {
s.classList.remove("o");
s.classList.remove("c");
} else {
if (s.classList.contains("o") == false && s.classList.contains("c") == false) {
s.classList.add("o");
}
}
});
}
async function RefreshCounters() {
if (opt.show_counter_tabs || opt.show_counter_tabs_hints) {
// if (opt.show_counter_tabs_hints) {
// document.querySelectorAll("#"+tt.active_group+" .tab").forEach(function(s){
// let title = s.childNodes[0].getAttribute("tabTitle");
// if (title != null) {
// s.childNodes[0].title = title;
// s.childNodes[0].childNodes[1].textContent = title;
// }
// });
// }
document.querySelectorAll("#"+tt.active_group+" .o.tab, #"+tt.active_group+" .c.tab").forEach(function(s){
if (opt.show_counter_tabs) {
s.childNodes[0].childNodes[1].childNodes[0].textContent = document.querySelectorAll("[id='" + s.id + "'] .tab").length;
}
if (opt.show_counter_tabs_hints) {
let title = s.childNodes[0].getAttribute("tabTitle");
s.childNodes[0].title = (document.querySelectorAll("[id='" + s.id + "'] .tab").length +" • ") + title;
}
});
// ·
document.querySelectorAll("#"+tt.active_group+" .folder").forEach(function(s){
if (opt.show_counter_tabs && tt.folders[s.id]) {
s.childNodes[0].childNodes[1].childNodes[0].textContent = document.querySelectorAll("[id='" + s.id + "'] .tab").length;
}
if (opt.show_counter_tabs_hints && tt.folders[s.id]) {
s.childNodes[0].title = (document.querySelectorAll("[id='" + s.id + "'] .tab").length +" • ") + tt.folders[s.id].name;
}
});
}
}
async function RefreshTabCounter(tabId) {
let t = document.getElementById(tabId);
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;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,415 +1,283 @@
// 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/
function Loadi18n() {
// toolbar labels
document.querySelectorAll(".button, .manager_window_toolbar_button").forEach(function(s){
s.title = chrome.i18n.getMessage(s.id);
});
// menu labels and edit group dialog labels
document.querySelectorAll(".menu_item, .edit_dialog_button, #manager_window_header_title, .manager_window_label").forEach(function(s){
s.textContent = chrome.i18n.getMessage(s.id);
});
function Theme_RestorePinListRowSettings() {
plist = document.getElementById("pin_list");
if (opt.pin_list_multi_row) {
plist.style.whiteSpace = "normal";
plist.style.overflowX = "hidden";
} else {
plist.style.whiteSpace = "";
plist.style.overflowX = "";
}
DOM_RefreshGUI();
}
function RestorePinListRowSettings() {
plist = document.getElementById("pin_list");
if (opt.pin_list_multi_row) {
plist.style.whiteSpace = "normal";
plist.style.overflowX = "hidden";
} else {
plist.style.whiteSpace = "";
plist.style.overflowX = "";
}
RefreshGUI();
}
function ApplyTheme(theme) {
RestoreStateOfGroupsToolbar();
ApplySizeSet(theme["TabsSizeSetNumber"]);
ApplyColorsSet(theme["ColorsSet"]);
ApplyTabsMargins(theme["TabsMargins"]);
RefreshGUI();
for (var groupId in tt.groups) {
let groupTitle = document.getElementById("_gte"+groupId);
if (groupTitle != null && tt.groups[groupId].font == "") {
groupTitle.style.color = "";
}
}
Loadi18n();
function Theme_ApplyTheme(theme) {
Groups_RestoreStateOfGroupsToolbar();
Theme_ApplySizeSet(theme["TabsSizeSetNumber"]);
Theme_ApplyColorsSet(theme["ColorsSet"]);
Theme_ApplyTabsMargins(theme["TabsMargins"]);
Theme_ApplyBlinking();
DOM_RefreshGUI();
// for some reason (top) text position is different in chromium !?
// if (browserId != "F") {
// document.styleSheets[document.styleSheets.length-1].insertRule(".tab_title, .folder_title { margin-top: 1px; }", document.styleSheets[document.styleSheets.length-1].cssRules.length);
// }
for (var groupId in tt.groups) {
let groupTitle = document.getElementById("_gte" + groupId);
if (groupTitle != null && tt.groups[groupId].font == "") groupTitle.style.color = "";
}
DOM_Loadi18n();
}
// theme colors is an object with css variables (but without --), for example; {"button_background": "#f2f2f2", "filter_box_border": "#cccccc"}
function ApplyColorsSet(ThemeColors){
let css_variables = "";
for (let css_variable in ThemeColors) {
css_variables = css_variables + "--" + css_variable + ":" + ThemeColors[css_variable] + ";";
}
for (let si = 0; si < document.styleSheets.length; si++) {
if (document.styleSheets[si].ownerNode.id == "theme_colors") {
document.styleSheets[si].deleteRule(document.styleSheets[si].cssRules.length-1);
document.styleSheets[si].insertRule("body { "+css_variables+" }", document.styleSheets[si].cssRules.length);
}
}
function Theme_ApplyColorsSet(ThemeColors) {
let css_variables = "";
for (let css_variable in ThemeColors) {
css_variables = css_variables + "--" + css_variable + ":" + ThemeColors[css_variable] + ";";
}
for (let si = 0; si < document.styleSheets.length; si++) {
if (document.styleSheets[si].ownerNode.id == "theme_colors") {
document.styleSheets[si].deleteRule(document.styleSheets[si].cssRules.length - 1);
document.styleSheets[si].insertRule("body { " + css_variables + " }", document.styleSheets[si].cssRules.length);
}
}
}
function ApplySizeSet(size){
for (let si = 0; si < document.styleSheets.length; si++) {
if ((document.styleSheets[si].ownerNode.id).match("sizes_preset") != null) {
if (document.styleSheets[si].ownerNode.id == "sizes_preset_"+size) {
document.styleSheets.item(si).disabled = false;
} else {
document.styleSheets.item(si).disabled = true;
}
}
}
if (browserId == "F") {
// for some reason top position for various things is different in firefox?????
if (size > 1) {
document.styleSheets[document.styleSheets.length-1].insertRule(".tab_header>.tab_title { margin-top: -1px; }", document.styleSheets[document.styleSheets.length-1].cssRules.length);
} else {
document.styleSheets[document.styleSheets.length-1].insertRule(".tab_header>.tab_title { margin-top: 0px; }", document.styleSheets[document.styleSheets.length-1].cssRules.length);
}
}
function Theme_ApplySizeSet(size) {
for (let si = 0; si < document.styleSheets.length; si++) {
if ((document.styleSheets[si].ownerNode.id).match("sizes_preset") != null) {
if (document.styleSheets[si].ownerNode.id == "sizes_preset_" + size) {
document.styleSheets.item(si).disabled = false;
} else {
document.styleSheets.item(si).disabled = true;
}
}
}
}
function ApplyTabsMargins(size){
for (let si = 0; si < document.styleSheets.length; si++) {
if ((document.styleSheets[si].ownerNode.id).match("tabs_margin") != null) {
if (document.styleSheets[si].ownerNode.id == "tabs_margin_"+size) {
document.styleSheets.item(si).disabled = false;
} else {
document.styleSheets.item(si).disabled = true;
}
}
}
function Theme_ApplyTabsMargins(size) {
for (let si = 0; si < document.styleSheets.length; si++) {
if ((document.styleSheets[si].ownerNode.id).match("tabs_margin") != null) {
if (document.styleSheets[si].ownerNode.id == "tabs_margin_" + size) {
document.styleSheets.item(si).disabled = false;
} else {
document.styleSheets.item(si).disabled = true;
}
}
}
}
function GetCurrentToolbar(storage) {
if (storage["toolbar"]) {
return storage["toolbar"];
} else {
return DefaultToolbar;
}
function Theme_ApplyBlinking() {
for (let si = 0; si < document.styleSheets.length; si++) {
if ((document.styleSheets[si].ownerNode.id).match("blinking_pins") != null) {
if (opt.pin_attention_blinking) {
document.styleSheets.item(si).disabled = false;
} else {
document.styleSheets.item(si).disabled = true;
}
}
if ((document.styleSheets[si].ownerNode.id).match("blinking_audio") != null) {
if (opt.audio_blinking) {
document.styleSheets.item(si).disabled = false;
} else {
document.styleSheets.item(si).disabled = true;
}
}
}
}
function Theme_GetCurrentToolbar(storage) {
if (storage["toolbar"]) {
return storage["toolbar"];
} else {
return DefaultToolbar;
}
}
function GetCurrentTheme(storage) {
if (storage["current_theme"] && storage["themes"] && storage["themes"][storage["current_theme"]]) {
let theme = storage["themes"][storage["current_theme"]];
let correctedTheme = CheckTheme(theme);
if (correctedTheme.theme_version < 4 && storage["preferences"].show_toolbar == undefined) {
opt.show_toolbar = correctedTheme.ToolbarShow;
SavePreferences();
}
return correctedTheme;
} else {
return DefaultTheme;
}
function Theme_GetCurrentTheme(storage) {
if (storage["current_theme"] && storage["themes"] && storage["themes"][storage["current_theme"]]) {
let theme = storage["themes"][storage["current_theme"]];
let correctedTheme = Theme_CheckTheme(theme);
if (correctedTheme.theme_version < 4 && storage["preferences"].show_toolbar == undefined) {
opt.show_toolbar = correctedTheme.ToolbarShow;
Preferences_SavePreferences(opt);
}
return correctedTheme;
} else {
return DefaultTheme;
}
}
// OPTIONS PAGE
function LoadTheme(ThemeId, reloadInSidebar) {
document.querySelectorAll(".theme_buttons").forEach(function(s){
s.disabled = true;
});
chrome.storage.local.set({current_theme: ThemeId}, function() {
chrome.storage.local.get(null, function(storage) {
SelectedTheme = Object.assign({}, GetCurrentTheme(storage));
setTimeout(function() {
document.getElementById("new_theme_name").value = SelectedTheme.theme_name;
setTimeout(function() {
// SetToolbarEvents(true, false, false, "");
RemoveToolbarEditEvents();
ApplySizeSet(SelectedTheme["TabsSizeSetNumber"]);
ApplyColorsSet(SelectedTheme["ColorsSet"]);
document.getElementById("_gtetab_list").style.color = "";
document.getElementById("_gtetab_list2").style.color = "";
if (SelectedTheme["TabsMargins"]) {
document.getElementById("tabs_margin_spacing")[SelectedTheme["TabsMargins"]].checked = true;
ApplyTabsMargins(SelectedTheme["TabsMargins"]);
} else {
document.getElementById("tabs_margin_spacing")["2"].checked = true;
}
if (reloadInSidebar) {
chrome.runtime.sendMessage({command: "reload_theme", ThemeId: ThemeId, theme: SelectedTheme});
}
document.querySelectorAll(".theme_buttons").forEach(function(s){
s.disabled = false;
});
}, 200);
}, 200);
});
});
function Theme_LoadTheme(ThemeId, reloadInSidebar) {
let query = document.querySelectorAll(".theme_buttons");
for (let s of query) {
s.disabled = true;
}
chrome.storage.local.set({current_theme: ThemeId}, function() {
chrome.storage.local.get(null, function(storage) {
SelectedTheme = Object.assign({}, Theme_GetCurrentTheme(storage));
setTimeout(function() {
document.getElementById("new_theme_name").value = SelectedTheme.theme_name;
setTimeout(function() {
RemoveToolbarEditEvents();
Theme_ApplySizeSet(SelectedTheme["TabsSizeSetNumber"]);
Theme_ApplyColorsSet(SelectedTheme["ColorsSet"]);
document.getElementById("_gtetab_list").style.color = "";
document.getElementById("_gtetab_list2").style.color = "";
if (SelectedTheme["TabsMargins"]) {
document.getElementById("tabs_margin_spacing")[SelectedTheme["TabsMargins"]].checked = true;
Theme_ApplyTabsMargins(SelectedTheme["TabsMargins"]);
} else {
document.getElementById("tabs_margin_spacing")["2"].checked = true;
}
if (reloadInSidebar) chrome.runtime.sendMessage({command: "reload_theme", ThemeId: ThemeId, theme: SelectedTheme});
let query = document.querySelectorAll(".theme_buttons");
for (let s of query) {
s.disabled = false;
}
}, 200);
}, 200);
});
});
}
function SaveTheme(ThemeId) {
chrome.storage.local.get(null, function(storage) {
SelectedTheme.theme_version = DefaultTheme.theme_version;
let LSthemes = storage.themes ? Object.assign({}, storage.themes) : {};
LSthemes[ThemeId] = Object.assign({}, SelectedTheme);
chrome.storage.local.set({themes: LSthemes});
chrome.runtime.sendMessage({command: "reload_theme", ThemeId: ThemeId, theme: SelectedTheme});
return SelectedTheme;
});
function Theme_SaveTheme(ThemeId) {
chrome.storage.local.get(null, function(storage) {
SelectedTheme.theme_version = DefaultTheme.theme_version;
let LSthemes = storage.themes ? Object.assign({}, storage.themes) : {};
LSthemes[ThemeId] = Object.assign({}, SelectedTheme);
chrome.storage.local.set({themes: LSthemes});
chrome.runtime.sendMessage({command: "reload_theme", ThemeId: ThemeId, theme: SelectedTheme});
return SelectedTheme;
});
}
function AddNewTheme() {
let ThemeId = GenerateRandomID() + GenerateRandomID();
let ThemeList = document.getElementById("theme_list");
let ThemeNameBox = document.getElementById("new_theme_name");
let NewName = ThemeNameBox.value;
if (ThemeNameBox.value == "") {
alert(chrome.i18n.getMessage("options_theme_name_cannot_be_empty"));
return;
}
SelectedTheme = Object.assign({}, DefaultTheme);
SelectedTheme["ColorsSet"] = {};
// let Names = [];
// for (let i = 0; i < ThemeList.options.length; i++) {
// Names.push(ThemeList.options[i].text);
// }
// while (Names.indexOf(NewName) != -1) {
// let matched = NewName.match(/\(\d+\)+/);
// if (matched != null && matched.length > 0) {
// NewName = NewName.replace(matched[0], ("(" + (parseInt(matched[0].match(/\d+/)[0]) + 1 ) + ")") );
// } else {
// NewName = NewName + "(1)";
// }
// }
ThemeNameBox.value = NewName;
SelectedTheme["theme_name"] = NewName;
themes.push(ThemeId);
let ThemeNameOption = document.createElement("option");
ThemeNameOption.value = ThemeId;
ThemeNameOption.text = NewName;
ThemeList.add(ThemeNameOption);
ThemeList.selectedIndex = ThemeList.options.length-1;
SaveTheme(ThemeId);
setTimeout(function() {
LoadTheme(ThemeId, true);
}, 50);
chrome.storage.local.set({current_theme: ThemeId});
RefreshFields();
function Theme_AddNewTheme() {
let ThemeId = GenerateRandomID() + GenerateRandomID();
let ThemeList = document.getElementById("theme_list");
let ThemeNameBox = document.getElementById("new_theme_name");
let NewName = ThemeNameBox.value;
if (ThemeNameBox.value == "") {
alert(chrome.i18n.getMessage("options_theme_name_cannot_be_empty"));
return;
}
SelectedTheme = Object.assign({}, DefaultTheme);
SelectedTheme["ColorsSet"] = {};
ThemeNameBox.value = NewName;
SelectedTheme["theme_name"] = NewName;
themes.push(ThemeId);
DOM_New("option", ThemeList, {value: ThemeId, text: NewName});
ThemeList.selectedIndex = ThemeList.options.length - 1;
Theme_SaveTheme(ThemeId);
setTimeout(function() {Theme_LoadTheme(ThemeId, true);}, 50);
chrome.storage.local.set({current_theme: ThemeId});
RefreshFields();
}
function DeleteSelectedTheme() {
chrome.storage.local.get(null, function(storage) {
let LSthemes = storage.themes ? Object.assign({}, storage.themes) : {};
let ThemeList = document.getElementById("theme_list");
themes.splice(ThemeList.selectedIndex, 1);
if (LSthemes[current_theme]) {
delete LSthemes[current_theme];
}
chrome.storage.local.set({themes: LSthemes});
ThemeList.remove(ThemeList.selectedIndex);
current_theme = (ThemeList.options.length > 0) ? ThemeList.value : "default";
chrome.storage.local.set({current_theme: current_theme});
if (ThemeList.options.length == 0) {
current_theme = "";
SelectedTheme = Object.assign({}, DefaultTheme);
SelectedTheme["ColorsSet"] = {};
chrome.storage.local.set({themes: {}});
setTimeout(function() {
chrome.runtime.sendMessage({command: "reload_theme", themeName: "", theme: SelectedTheme});
}, 500);
}
LoadTheme(current_theme, true);
RefreshFields();
});
function Theme_DeleteSelectedTheme() {
chrome.storage.local.get(null, function(storage) {
let LSthemes = storage.themes ? Object.assign({}, storage.themes) : {};
let ThemeList = document.getElementById("theme_list");
themes.splice(ThemeList.selectedIndex, 1);
if (LSthemes[current_theme]) delete LSthemes[current_theme];
chrome.storage.local.set({themes: LSthemes});
ThemeList.remove(ThemeList.selectedIndex);
current_theme = (ThemeList.options.length > 0) ? ThemeList.value : "default";
chrome.storage.local.set({current_theme: current_theme});
if (ThemeList.options.length == 0) {
current_theme = "";
SelectedTheme = Object.assign({}, DefaultTheme);
SelectedTheme["ColorsSet"] = {};
chrome.storage.local.set({themes: {}});
setTimeout(function() {chrome.runtime.sendMessage({command: "reload_theme", themeName: "", theme: SelectedTheme});}, 500);
}
Theme_LoadTheme(current_theme, true);
RefreshFields();
});
}
function RenameSelectedTheme() {
let ThemeList = document.getElementById("theme_list");
let ThemeNameBox = document.getElementById("new_theme_name");
// for (let i = 0; i < ThemeList.options.length; i++) {
// if (ThemeNameBox.value == ThemeList.options[i].text){
// alert(chrome.i18n.getMessage("options_there_is_a_theme_with_this_name"));
// return;
// }
// }
if (ThemeNameBox.value == "") {
alert(chrome.i18n.getMessage("options_theme_name_cannot_be_empty"));
return;
}
chrome.storage.local.get(null, function(storage) {
let LSthemes = storage.themes ? Object.assign({}, storage.themes) : {};
ThemeList.options[ThemeList.selectedIndex].text = ThemeNameBox.value;
SelectedTheme["theme_name"] = ThemeNameBox.value;
LSthemes[current_theme]["theme_name"] = ThemeNameBox.value;
chrome.storage.local.set({themes: LSthemes});
chrome.storage.local.set({current_theme: current_theme});
});
function Theme_RenameSelectedTheme() {
let ThemeList = document.getElementById("theme_list");
let ThemeNameBox = document.getElementById("new_theme_name");
if (ThemeNameBox.value == "") {
alert(chrome.i18n.getMessage("options_theme_name_cannot_be_empty"));
return;
}
chrome.storage.local.get(null, function(storage) {
let LSthemes = storage.themes ? Object.assign({}, storage.themes) : {};
ThemeList.options[ThemeList.selectedIndex].text = ThemeNameBox.value;
SelectedTheme["theme_name"] = ThemeNameBox.value;
LSthemes[current_theme]["theme_name"] = ThemeNameBox.value;
chrome.storage.local.set({themes: LSthemes});
chrome.storage.local.set({current_theme: current_theme});
});
}
function CheckTheme(theme) {
if (theme.theme_version < 2) {
theme["ColorsSet"]["scrollbar_height"] = theme.ScrollbarPinList + "px";
theme["ColorsSet"]["scrollbar_width"] = theme.ScrollbarTabList + "px";
}
if (theme["TabsMargins"] == undefined) {
theme["TabsMargins"] = "2";
}
if (theme.theme_version < 4) {
delete theme["ColorsSet"]["active_font_weight"];
delete theme["ColorsSet"]["expand_lines"];
delete theme["ColorsSet"]["expand_open_border"];
delete theme["ColorsSet"]["expand_closed_border"];
if (theme["ColorsSet"]["toolbar_background"]) {
theme["ColorsSet"]["toolbar_shelf_background"] = theme["ColorsSet"]["toolbar_background"];
theme["ColorsSet"]["button_on_background"] = theme["ColorsSet"]["toolbar_background"];
}
if (theme["ColorsSet"]["button_icons"]) {
theme["ColorsSet"]["button_on_icons"] = theme["ColorsSet"]["button_icons"];
theme["ColorsSet"]["button_shelf_icons"] = theme["ColorsSet"]["button_icons"];
}
if (theme["ColorsSet"]["button_background"]) {
theme["ColorsSet"]["button_shelf_background"] = theme["ColorsSet"]["button_background"];
}
if (theme["ColorsSet"]["button_hover_background"]) {
theme["ColorsSet"]["button_shelf_hover_background"] = theme["ColorsSet"]["button_hover_background"];
}
if (theme["ColorsSet"]["button_border"]) {
theme["ColorsSet"]["button_shelf_border"] = theme["ColorsSet"]["button_border"];
}
if (theme["ColorsSet"]["button_hover_border"]) {
theme["ColorsSet"]["button_shelf_hover_border"] = theme["ColorsSet"]["button_hover_border"];
}
if (theme["ColorsSet"]["button_icons_hover"]) {
theme["ColorsSet"]["button_shelf_icons_hover"] = theme["ColorsSet"]["button_icons_hover"];
}
if (theme["ColorsSet"]["expand_hover_background"]) {
theme["ColorsSet"]["folder_icon_hover"] = theme["ColorsSet"]["expand_hover_background"];
}
if (theme["ColorsSet"]["expand_closed_background"]) {
theme["ColorsSet"]["folder_icon_closed"] = theme["ColorsSet"]["expand_closed_background"];
}
if (theme["ColorsSet"]["expand_open_background"]) {
theme["ColorsSet"]["folder_icon_open"] = theme["ColorsSet"]["expand_open_background"];
}
}
return theme;
function Theme_CheckTheme(theme) {
if (theme.theme_version < 2) {
theme["ColorsSet"]["scrollbar_height"] = theme.ScrollbarPinList + "px";
theme["ColorsSet"]["scrollbar_width"] = theme.ScrollbarTabList + "px";
}
if (theme["TabsMargins"] == undefined) theme["TabsMargins"] = "2";
if (theme.theme_version < 4) {
delete theme["ColorsSet"]["active_font_weight"];
delete theme["ColorsSet"]["expand_lines"];
delete theme["ColorsSet"]["expand_open_border"];
delete theme["ColorsSet"]["expand_closed_border"];
if (theme["ColorsSet"]["toolbar_background"]) {
theme["ColorsSet"]["toolbar_shelf_background"] = theme["ColorsSet"]["toolbar_background"];
theme["ColorsSet"]["button_on_background"] = theme["ColorsSet"]["toolbar_background"];
}
if (theme["ColorsSet"]["button_icons"]) {
theme["ColorsSet"]["button_on_icons"] = theme["ColorsSet"]["button_icons"];
theme["ColorsSet"]["button_shelf_icons"] = theme["ColorsSet"]["button_icons"];
}
if (theme["ColorsSet"]["button_background"]) theme["ColorsSet"]["button_shelf_background"] = theme["ColorsSet"]["button_background"];
if (theme["ColorsSet"]["button_hover_background"]) theme["ColorsSet"]["button_shelf_hover_background"] = theme["ColorsSet"]["button_hover_background"];
if (theme["ColorsSet"]["button_border"]) theme["ColorsSet"]["button_shelf_border"] = theme["ColorsSet"]["button_border"];
if (theme["ColorsSet"]["button_hover_border"]) theme["ColorsSet"]["button_shelf_hover_border"] = theme["ColorsSet"]["button_hover_border"];
if (theme["ColorsSet"]["button_icons_hover"]) theme["ColorsSet"]["button_shelf_icons_hover"] = theme["ColorsSet"]["button_icons_hover"];
if (theme["ColorsSet"]["expand_hover_background"]) theme["ColorsSet"]["folder_icon_hover"] = theme["ColorsSet"]["expand_hover_background"];
if (theme["ColorsSet"]["expand_closed_background"]) theme["ColorsSet"]["folder_icon_closed"] = theme["ColorsSet"]["expand_closed_background"];
if (theme["ColorsSet"]["expand_open_background"]) theme["ColorsSet"]["folder_icon_open"] = theme["ColorsSet"]["expand_open_background"];
}
return theme;
}
function ImportTheme() {
var file = document.getElementById("file_import");
var fr = new FileReader();
if (file.files[0] == undefined) return;
fr.readAsText(file.files[0]);
fr.onload = function() {
var data = fr.result;
file.parentNode.removeChild(file);
var themeObj = JSON.parse(data);
if (themeObj.theme_version > DefaultTheme["theme_version"]) {
alert(chrome.i18n.getMessage("options_loaded_theme_newer_version"));
}
if (themeObj.theme_version < DefaultTheme["theme_version"]) {
alert(chrome.i18n.getMessage("options_loaded_theme_older_version"));
}
if (themeObj.theme_version <= DefaultTheme["theme_version"]) {
let ThemeList = document.getElementById("theme_list");
let ThemeId = GenerateRandomID() + GenerateRandomID();
let correctedTheme = CheckTheme(themeObj);
SelectedTheme = Object.assign({}, DefaultTheme);
for (var val in correctedTheme.ColorsSet) {
SelectedTheme["ColorsSet"][val] = correctedTheme.ColorsSet[val];
}
SelectedTheme["TabsSizeSetNumber"] = correctedTheme.TabsSizeSetNumber;
SelectedTheme["TabsMargins"] = correctedTheme["TabsMargins"];
SelectedTheme["theme_version"] = DefaultTheme["theme_version"];
// let Names = [];
// for (let i = 0; i < ThemeList.options.length; i++) {
// Names.push(ThemeList.options[i].text);
// }
// if (Names.indexOf(correctedTheme.theme_name) == -1) {
SelectedTheme["theme_name"] = correctedTheme.theme_name;
// } else {
// let NewName = correctedTheme.theme_name;
// while (Names.indexOf(NewName) != -1) {
// let matched = NewName.match(/\(\d+\)+/);
// if (matched != null && matched.length > 0) {
// NewName = NewName.replace(matched[0], ("(" + (parseInt(matched[0].match(/\d+/)[0]) + 1 ) + ")") );
// } else {
// NewName = NewName + "(1)";
// }
// }
// SelectedTheme["theme_name"] = NewName;
// }
themes.push(ThemeId);
SaveTheme(ThemeId);
var theme_name = document.createElement("option");
theme_name.value = ThemeId;
theme_name.text = SelectedTheme["theme_name"];
ThemeList.add(theme_name);
ThemeList.selectedIndex = ThemeList.options.length-1;
current_theme = ThemeId;
document.createElement("new_theme_name").value = ThemeId;
setTimeout(function() {
LoadTheme(ThemeId, true);
}, 500);
RefreshFields();
DefaultTheme["ColorsSet"] = {};
chrome.storage.local.set({current_theme: ThemeId});
}
}
function Theme_ImportTheme() {
var file = document.getElementById("file_import");
var fr = new FileReader();
if (file.files[0] == undefined) return;
fr.readAsText(file.files[0]);
fr.onload = function() {
var data = fr.result;
file.parentNode.removeChild(file);
var themeObj = JSON.parse(data);
if (themeObj.theme_version > DefaultTheme["theme_version"]) alert(chrome.i18n.getMessage("options_loaded_theme_newer_version"));
if (themeObj.theme_version < DefaultTheme["theme_version"]) alert(chrome.i18n.getMessage("options_loaded_theme_older_version"));
if (themeObj.theme_version <= DefaultTheme["theme_version"]) {
let ThemeList = document.getElementById("theme_list");
let ThemeId = GenerateRandomID() + GenerateRandomID();
let correctedTheme = Theme_CheckTheme(themeObj);
SelectedTheme = Object.assign({}, DefaultTheme);
for (var val in correctedTheme.ColorsSet) {
SelectedTheme["ColorsSet"][val] = correctedTheme.ColorsSet[val];
}
SelectedTheme["TabsSizeSetNumber"] = correctedTheme.TabsSizeSetNumber;
SelectedTheme["TabsMargins"] = correctedTheme["TabsMargins"];
SelectedTheme["theme_version"] = DefaultTheme["theme_version"];
SelectedTheme["theme_name"] = correctedTheme.theme_name;
themes.push(ThemeId);
Theme_SaveTheme(ThemeId);
let theme_name = DOM_New("option", undefined, {value: ThemeId, text: SelectedTheme["theme_name"]});
ThemeList.add(theme_name);
ThemeList.selectedIndex = ThemeList.options.length - 1;
current_theme = ThemeId;
document.createElement("new_theme_name").value = ThemeId;
setTimeout(function() {Theme_LoadTheme(ThemeId, true);}, 500);
RefreshFields();
DefaultTheme["ColorsSet"] = {};
chrome.storage.local.set({current_theme: ThemeId});
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,401 +1,19 @@
// 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/
function RecheckFirefox() {
chrome.tabs.query({pinned: false, currentWindow: true}, function(tabs) {
if (tabs.length > 1) {
let last_tabId = tabs[tabs.length-1].id;
let p = [];
let p_tt = [];
let t_ref = {};
let t_ind = 0;
let ok = 0;
let ti = 0;
let tc = tabs.length;
for (ti = 0; ti < tc; ti++) {
let tabId = tabs[ti].id;
p.push("");
p_tt.push("");
let t = Promise.resolve(browser.sessions.getTabValue(tabId, "TTdata")).then(function(TabData) {
if (TabData != undefined) {
t_ref[TabData.ttid] = tabs[t_ind].id;
p_tt[t_ind] = TabData.parent_ttid;
p[t_ind] = TabData.parent;
}
t_ind++;
if (tabId == last_tabId) {
let i = 0;
for (i = 0; i < p.length; i++) {
if (t_ref[p_tt[i]]) {
p[i] = t_ref[p_tt[i]];
}
}
for (i = 0; i < p.length; i++) {
let Tab = document.getElementById(tabs[i].id);
if (Tab && p[i] == Tab.parentNode.parentNode.id) {
ok++;
}
}
if (ok < tabs.length*0.5) {
if (opt.debug) {
log("emergency reload");
}
chrome.storage.local.set({emergency_reload: true});
chrome.runtime.sendMessage({command: "reload"});
chrome.runtime.sendMessage({command: "reload_sidebar"});
location.reload();
} else {
if (opt.debug) {
log("f: RecheckFirefox, ok");
}
}
}
});
}
}
});
function Utils_RGBtoHex(color) { // color in format "rgb(r,g,b)" or simply "r,g,b" (can have spaces, but must contain "," between values)
color = color.replace(/[rgb(]|\)|\s/g, "");
color = color.split(",");
return color.map(function(v) {return ("0" + Math.min(Math.max(parseInt(v), 0), 255).toString(16)).slice(-2);}).join("");
}
function SavePreferences() {
chrome.storage.local.set({preferences: opt});
chrome.runtime.sendMessage({command: "reload_options", opt: opt});
function Utils_HexToRGB(hex, alpha) {
hex = hex.replace('#', '');
let r = parseInt(hex.length == 3 ? hex.slice(0, 1).repeat(2) : hex.slice(0, 2), 16);
let g = parseInt(hex.length == 3 ? hex.slice(1, 2).repeat(2) : hex.slice(2, 4), 16);
let b = parseInt(hex.length == 3 ? hex.slice(2, 3).repeat(2) : hex.slice(4, 6), 16);
if (alpha) {
return 'rgba(' + r + ', ' + g + ', ' + b + ', ' + alpha + ')';
} else {
return 'rgb(' + r + ', ' + g + ', ' + b + ')';
}
}
function LoadDefaultPreferences() {
opt = Object.assign({}, DefaultPreferences);
function Utils_log(log) {
chrome.runtime.sendMessage({command: "debug", log: log});
}
function ShowOpenFileDialog(extension) {
let body = document.getElementById("body");
let inp = document.createElement("input");
inp.id = "file_import";
inp.type = "file";
inp.accept = extension;
inp.style.display = "none";
body.appendChild(inp);
inp.click();
return inp;
}
function SaveFile(filename, extension, data) {
let file = new File([JSON.stringify(data)], filename+"."+extension, {type: "text/"+extension+";charset=utf-8"} );
let body = document.getElementById("body");
let savelink = document.createElement("a");
savelink.href = URL.createObjectURL(file);
savelink.fileSize = file.size;
savelink.target = "_blank";
savelink.style.display = "none";
savelink.type = "file";
savelink.download = filename+"."+extension;
body.appendChild(savelink);
setTimeout(function() {
savelink.click();
setTimeout(function() {
savelink.parentNode.removeChild(savelink);
}, 60000);
}, 10);
}
function AppendToNode(Node, AppendNode) {
if (Node != null && AppendNode != null) {
AppendNode.appendChild(Node);
}
}
function InsterBeforeNode(Node, BeforeNode) {
if (Node != null && BeforeNode != null) {
BeforeNode.parentNode.insertBefore(Node, BeforeNode);
}
}
function InsterAfterNode(Node, AfterNode) {
if (Node != null && AfterNode != null) {
if (AfterNode.nextSibling != null) {
AfterNode.parentNode.insertBefore(Node, AfterNode.nextSibling);
} else {
AfterNode.parentNode.appendChild(Node);
}
}
}
function HideRenameDialogs() {
document.querySelectorAll(".edit_dialog").forEach(function(s){
s.style.display = "none";
s.style.top = "-500px";
s.style.left = "-500px";
});
}
function GetParentsByClass(Node, Class) {
let Parents = [];
let ParentNode = Node;
while (ParentNode.parentNode != null) {
if (ParentNode.parentNode.classList != undefined && ParentNode.parentNode.classList.contains(Class)) {
Parents.push(ParentNode.parentNode);
}
ParentNode = ParentNode.parentNode;
}
return Parents;
}
function GetParentsBy2Classes(Node, ClassA, ClassB) {
let Parents = [];
let ParentNode = Node;
while (ParentNode.parentNode != null) {
if (ParentNode.parentNode.classList != undefined && ParentNode.parentNode.classList.contains(ClassA) && ParentNode.parentNode.classList.contains(ClassB)) {
Parents.push(ParentNode.parentNode);
}
ParentNode = ParentNode.parentNode;
}
return Parents;
}
// color in format "rgb(r,g,b)" or simply "r,g,b" (can have spaces, but must contain "," between values)
function RGBtoHex(color){
color = color.replace(/[rgb(]|\)|\s/g, ""); color = color.split(","); return color.map(function(v){ return ("0"+Math.min(Math.max(parseInt(v), 0), 255).toString(16)).slice(-2); }).join("");
}
function HexToRGB(hex, alpha){
hex = hex.replace('#', '');
let r = parseInt(hex.length == 3 ? hex.slice(0, 1).repeat(2) : hex.slice(0, 2), 16);
let g = parseInt(hex.length == 3 ? hex.slice(1, 2).repeat(2) : hex.slice(2, 4), 16);
let b = parseInt(hex.length == 3 ? hex.slice(2, 3).repeat(2) : hex.slice(4, 6), 16);
if (alpha) { return 'rgba('+r+', '+g+', '+b+', '+alpha+')'; } else { return 'rgb('+r+', '+g+', '+b+')'; }
}
function GetSelectedFolders() {
if (opt.debug) {
log("f: GetSelectedFolders");
}
let res = {Folders: {}, FoldersSelected: [], TabsIds: [], TabsIdsParents: []};
document.querySelectorAll("#"+tt.active_group+" .selected_folder").forEach(function(s){
res.FoldersSelected.push(s.id);
res.Folders[s.id] = Object.assign({}, tt.folders[s.id]);
let Fchildren = document.querySelectorAll("#cf"+s.id+" .folder");
Fchildren.forEach(function(fc){
res.Folders[fc.id] = Object.assign({}, tt.folders[fc.id]);
});
let Tchildren = document.querySelectorAll("#ct"+s.id+" .tab");
Tchildren.forEach(function(tc){
res.TabsIds.push(parseInt(tc.id));
res.TabsIdsParents.push(tc.parentNode.id);
});
});
return res;
}
function GetSelectedTabs() {
let res = {TabsIds: [], TabsIdsParents: [], TabsIdsSelected: []};
document.querySelectorAll(".pin.selected_tab, #"+tt.active_group+" .selected_tab").forEach(function(s){
res.TabsIds.push(parseInt(s.id));
res.TabsIdsParents.push(s.parentNode.id);
res.TabsIdsSelected.push(parseInt(s.id));
let Tchildren = document.querySelectorAll("#ct"+s.id+" .tab");
Tchildren.forEach(function(tc){
res.TabsIds.push(parseInt(tc.id));
res.TabsIdsParents.push(tc.parentNode.id);
});
});
return res;
}
function FindTab(input) { // find and select tabs
let ButtonFilterClear = document.getElementById("button_filter_clear");
document.querySelectorAll(".filtered, .highlighted_search").forEach(function(s){
s.classList.remove("filtered");
s.classList.remove("selected_tab");
s.classList.remove("selected_last");
s.classList.remove("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) {
tabs.forEach(function(Tab) {
if (input == "*audible" || input == "*muted" || input == "*unloaded" || input == "*loaded") {
document.getElementById(Tab.id).classList.add("filtered");
document.getElementById(Tab.id).classList.add("selected_tab");
} else {
if (searchUrl) {
if (Tab.url.toLowerCase().match(input.toLowerCase())) {
document.getElementById(Tab.id).classList.add("filtered");
document.getElementById(Tab.id).classList.add("selected_tab");
}
}
if (searchTitle) {
if (Tab.title.toLowerCase().match(input.toLowerCase())) {
document.getElementById(Tab.id).classList.add("filtered");
document.getElementById(Tab.id).classList.add("selected_tab");
}
}
}
});
});
}
function Bookmark(rootNode) {
let ToolbarId = browserId == "F" ? "toolbar_____" : "1";
chrome.bookmarks.get(ToolbarId, function(list) {
chrome.bookmarks.search("TreeTabs", function(list) {
let TreeTabsId;
for (var elem in list) {
if (list[elem].parentId == ToolbarId) {
TreeTabsId = list[elem].id;
break;
}
}
if (TreeTabsId == undefined) {
chrome.bookmarks.create({parentId: ToolbarId, title: "TreeTabs"}, function(TreeTabsNew) {
TreeTabsId = TreeTabsNew.id;
});
Bookmark(rootNode);
return;
} else {
if (rootNode.classList.contains("tab")) {
chrome.tabs.get(parseInt(rootNode.id), function(tab) {
if (tab) {
chrome.bookmarks.create({parentId: TreeTabsId, title: tab.title}, function(root) {
document.querySelectorAll("[id='"+rootNode.id+"'], [id='"+rootNode.id+"'] .tab").forEach(function(s){
chrome.tabs.get(parseInt(s.id), function(tab){
if (tab) {
chrome.bookmarks.create({parentId: root.id, title: tab.title, url: tab.url });
}
});
});
});
}
});
}
if (rootNode.classList.contains("folder") || rootNode.classList.contains("group")) {
let rootName = labels.noname_group;
if (rootNode.classList.contains("folder") && tt.folders[rootNode.id]) {
rootName = tt.folders[rootNode.id].name;
}
if (rootNode.classList.contains("group") && tt.groups[rootNode.id]) {
rootName = tt.groups[rootNode.id].name;
}
chrome.bookmarks.create({parentId: TreeTabsId, title: rootName}, function(root) {
let foldersRefs = {};
let folders = document.querySelectorAll("#cf"+rootNode.id+" .folder");
folders.forEach(function(s){
if (tt.folders[s.id]) {
let ttId = s.id;
chrome.bookmarks.create({parentId: root.id, title: tt.folders[ttId].name}, function(Bkfolder) {
foldersRefs[ttId] = {ttid: ttId, id: Bkfolder.id, ttparent: tt.folders[ttId].parent, parent: root.id};
let elemInd = 0;
if (ttId == folders[folders.length-1].id) {
for (var elem in foldersRefs) {
let FolderTTId = foldersRefs[elem].ttid;
let BookmarkFolderId = foldersRefs[elem].id;
let TTParentId = foldersRefs[elem].ttparent;
if (foldersRefs[TTParentId]) {
foldersRefs[FolderTTId].parent = foldersRefs[TTParentId].id;
}
elemInd++;
if (elemInd == Object.keys(foldersRefs).length) {
elemInd = 0;
for (var elem in foldersRefs) {
let BookmarkFolderId = foldersRefs[elem].id;
let BookmarkFolderParentId = foldersRefs[elem].parent;
chrome.bookmarks.move(BookmarkFolderId, {parentId: BookmarkFolderParentId}, function(BkFinalfolder) {
document.querySelectorAll("#ct"+foldersRefs[elem].ttid+" .tab").forEach(function(s){
chrome.tabs.get(parseInt(s.id), function(tab){
if (tab) {
chrome.bookmarks.create({parentId: BkFinalfolder.id, title: tab.title, url: tab.url });
}
});
});
elemInd++;
});
}
}
}
}
});
}
});
document.querySelectorAll("#ct"+rootNode.id+" .tab").forEach(function(s){
chrome.tabs.get(parseInt(s.id), function(tab){
if (tab) {
chrome.bookmarks.create({parentId: root.id, title: tab.title, url: tab.url });
}
});
});
});
}
}
});
});
}
function ShowStatusBar(p) { // show, spinner, message
let status_bar = document.getElementById("status_bar");
let busy_spinner = document.getElementById("busy_spinner");
let status_message = document.getElementById("status_message");
if (p.show) {
status_bar.style.display = "block";
status_message.textContent = p.message;
if (p.spinner) {
busy_spinner.style.opacity = "1";
} else {
busy_spinner.style.opacity = "0";
}
} else {
busy_spinner.style.opacity = "0";
status_message.textContent = "";
status_bar.style.display = "none";
}
if (p.hideTimeout) {
setTimeout(function() {
busy_spinner.style.opacity = "0";
status_message.textContent = "";
status_bar.style.display = "none";
}, p.hideTimeout);
}
}
function log(log) {
if (opt.debug) {
chrome.runtime.sendMessage({command: "debug", log: log});
}
}

View File

@ -1,199 +1,138 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
<style id="pagestyle">
html,
body {
width:100%;
height:100%;
border:none;
margin:0;
padding:0;
white-space:nowrap;
overflow:hidden;
font-family:Arial;
-webkit-user-select:none;
-webkit-user-drag:none;
}
</style>
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_0.css" id="sizes_preset_0" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_1.css" id="sizes_preset_1" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_2.css" id="sizes_preset_2" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_3.css" id="sizes_preset_3" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_4.css" id="sizes_preset_4" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_tabs_margin_0.css" id="tabs_margin_0" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_tabs_margin_1.css" id="tabs_margin_1" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_tabs_margin_2.css" id="tabs_margin_2" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_colors.css" id="theme_colors" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme.css" id="theme" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_manager.css" id="manager" />
</head>
<body id="body" class="sidebar_body">
<head>
<meta charset="utf-8" />
<title></title>
<style id="pagestyle">
html,
body {
width: 100%;
height: 100%;
border: none;
margin: 0;
padding: 0;
white-space: nowrap;
overflow: hidden;
font-family: Arial;
-webkit-user-select: none;
-webkit-user-drag: none;
}
</style>
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_0.css" id="sizes_preset_0" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_1.css" id="sizes_preset_1" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_2.css" id="sizes_preset_2" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_3.css" id="sizes_preset_3" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_4.css" id="sizes_preset_4" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_size_preset_5.css" id="sizes_preset_5" />
<div id="DragImage" style="display: none; width:0px; height:0px;"></div>
<div class="toolbar" id="toolbar"></div>
<div id="toolbar_groups">
<div class="scroll_group" id="scroll_group_up"></div>
<div class="group_list" id="group_list"></div>
<div class="scroll_group" id="scroll_group_down"></div>
</div>
<div class="pin_list" id="pin_list"></div>
<div id="groups"></div>
<input type="color" id="color_picker" style="position:absolute; left:-1000px; top:-1000px; width:1px; height:1px; overflow:hidden;">
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_tabs_margin_0.css" id="tabs_margin_0" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_tabs_margin_1.css" id="tabs_margin_1" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_tabs_margin_2.css" id="tabs_margin_2" />
<ul class="edit_dialog" id="group_edit">
<input class="edit_dialog_edit_name text_input" id="group_edit_name" type="text"></input>
<div class="group_edit_color" id="group_edit_font"></div>
<br>
<div class="edit_dialog_discard" id="group_edit_discard"><span class="edit_dialog_button" id="group_edit_button_cancel"></span></div>
<div class="edit_dialog_confirm" id="group_edit_confirm"><span class="edit_dialog_button" id="group_edit_button_confirm"></span></div>
</ul>
<ul class="edit_dialog" id="folder_edit">
<input class="edit_dialog_edit_name text_input" id="folder_edit_name" type="text"></input>
<br>
<div class="edit_dialog_discard" id="folder_edit_discard"><span class="edit_dialog_button" id="folder_edit_button_cancel"></span></div>
<div class="edit_dialog_confirm" id="folder_edit_confirm"><span class="edit_dialog_button" id="folder_edit_button_confirm"></span></div>
</ul>
<ul class="edit_dialog" id="manager_window">
<div id="manager_window_header"><div id="manager_window_header_title"></div><div id="manager_window_close"><div class="close_img"></div></div></div>
<div id="manager_window_toolbar">
<div class="manager_window_toolbar_button mw_on" id="manager_window_groups_button">
<div class="manager_window_toolbar_button_img"></div>
</div>
<div class="manager_window_toolbar_button" id="manager_window_sessions_button">
<div class="manager_window_toolbar_button_img"></div>
</div>
<div class="manager_window_toolbar_button" id="manager_window_autosave_button">
<div class="manager_window_toolbar_button_img"></div>
</div>
</div>
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_colors.css" id="theme_colors" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme.css" id="theme" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_manager.css" id="manager" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_blinking_attention.css" id="blinking_pins" />
<link type="text/css" rel="stylesheet" media="all" href="theme/theme_blinking_audio.css" id="blinking_audio" />
</head>
<body id="body" class="sidebar_body">
<div id="DragImage" style="display: none; width:0px; height:0px;"></div>
<div class="toolbar" id="toolbar"></div>
<div id="toolbar_groups">
<div class="scroll_group" id="scroll_group_up"></div>
<div class="group_list" id="group_list"></div>
<div class="scroll_group" id="scroll_group_down"></div>
</div>
<div class="manager_window_panel mw_pan_on" id="manager_window_groups_panel">
<div class="manager_window_panel_buttons">
<div class="edit_dialog_confirm" id="manager_window_button_import_group"><span class="edit_dialog_button" id="manager_window_button_label_import_group"></span></div>
<div class="edit_dialog_confirm" id="manager_window_button_hibernate_group"><span class="edit_dialog_button" id="manager_window_button_label_hibernate_group"></span></div>
</div>
<div class="manager_window_list" id="manager_window_groups_list"></div>
</div>
<div class="pin_list" id="pin_list"></div>
<div id="groups"></div>
<div class="manager_window_panel" id="manager_window_sessions_panel">
<div class="manager_window_panel_buttons">
<div class="edit_dialog_confirm" id="manager_window_button_import_session"><span class="edit_dialog_button" id="manager_window_button_label_import_session"></span></div>
<div class="edit_dialog_confirm" id="manager_window_button_save_current_session"><span class="edit_dialog_button" id="manager_window_button_label_save_current_session"></span></div>
</div>
<div class="manager_window_list" id="manager_window_sessions_list"></div>
</div>
<div class="manager_window_panel" id="manager_window_autosave_panel">
<div class="manager_window_panel_buttons">
<span class="manager_window_label" id="manager_window_autosessions_maximum_saves_label"></span>
<br>
<input class="input_number" type="number" min="0" max="99999" step="1" id="manager_window_autosessions_maximum_saves"></input>
<br>
<span class="manager_window_label" id="manager_window_autosessions_save_timer_label"></span>
<br>
<input class="input_number" type="number" min="0" max="99999" step="1" id="manager_window_autosessions_save_timer"></input>
</div>
<div class="manager_window_list" id="manager_window_autosessions_list"></div>
</div>
</ul>
<div id="status_bar">
<div id="new_tab_floating_button_img"></div>
<div id="status_message"></div>
<div id="busy_spinner"></div>
</div>
<ul class="menu" id="main_menu">
<li class="menu_item" id="menu_new_pin"></li>
<div class="separator" id="separator_newt"></div>
<li class="menu_item" id="menu_new_tab"></li>
<div class="separator" id="separator_unpt"></div>
<li class="menu_item" id="menu_unpin_tab"></li>
<div class="separator" id="separator_pit"></div>
<li class="menu_item" id="menu_pin_tab"></li>
<div class="separator" id="separator_newf"></div>
<li class="menu_item" id="menu_new_folder"></li>
<div class="separator" id="separator_renf"></div>
<li class="menu_item" id="menu_rename_folder"></li>
<div class="separator" id="separator_delf"></div>
<li class="menu_item" id="menu_delete_folder"></li>
<div class="separator" id="separator_dupt"></div>
<li class="menu_item" id="menu_duplicate_tab"></li>
<div class="separator" id="separator_undclo"></div>
<li class="menu_item" id="menu_undo_close_tab"></li>
<div class="separator" id="separator_bkt"></div>
<li class="menu_item" id="menu_bookmark_tree"></li>
<div class="separator" id="separator_expat"></div>
<li class="menu_item" id="menu_expand_tree"></li>
<div class="separator" id="separator_collt"></div>
<li class="menu_item" id="menu_collapse_tree"></li>
<div class="separator" id="separator_expaa"></div>
<li class="menu_item" id="menu_expand_all"></li>
<div class="separator" id="separator_colla"></div>
<li class="menu_item" id="menu_collapse_all"></li>
<div class="separator" id="separator_deta"></div>
<li class="menu_item" id="menu_detach_tab"></li>
<div class="separator" id="separator_rel"></div>
<li class="menu_item" id="menu_reload_tab"></li>
<div class="separator" id="separator_unlo"></div>
<li class="menu_item" id="menu_unload"></li>
<div class="separator" id="separator_clo"></div>
<li class="menu_item" id="menu_close"></li>
<div class="separator" id="separator_clot"></div>
<li class="menu_item" id="menu_close_tree"></li>
<div class="separator" id="separator_cloo"></div>
<li class="menu_item" id="menu_close_other"></li>
<div class="separator" id="separator_mut"></div>
<li class="menu_item" id="menu_mute_tab"></li>
<div class="separator" id="separator_mutt"></div>
<li class="menu_item" id="menu_mute_tree"></li>
<div class="separator" id="separator_unmu"></div>
<li class="menu_item" id="menu_unmute_tab"></li>
<div class="separator" id="separator_unmut"></div>
<li class="menu_item" id="menu_unmute_tree"></li>
<div class="separator" id="separator_mutot"></div>
<li class="menu_item" id="menu_mute_other"></li>
<div class="separator" id="separator_unmutot"></div>
<li class="menu_item" id="menu_unmute_other"></li>
<div class="separator" id="separator_newg"></div>
<li class="menu_item" id="menu_new_group"></li>
<div class="separator" id="separator_reng"></div>
<li class="menu_item" id="menu_rename_group"></li>
<div class="separator" id="separator_delg"></div>
<li class="menu_item" id="menu_delete_group"></li>
<div class="separator" id="separator_delgclo"></div>
<li class="menu_item" id="menu_delete_group_tabs_close"></li>
<div class="separator" id="separator_gunlo"></div>
<li class="menu_item" id="menu_groups_unload"></li>
<div class="separator" id="separator_ghiber"></div>
<li class="menu_item" id="menu_groups_hibernate"></li>
<div class="separator" id="separator_gtbcl"></div>
<li class="menu_item" id="menu_group_tabs_close"></li>
<div class="separator" id="separator_gbk"></div>
<li class="menu_item" id="menu_bookmark_group"></li>
<div class="separator" id="separator_tts"></div>
<li class="menu_item" id="menu_manager_window"></li>
<li class="menu_item" id="menu_treetabs_settings"></li>
</ul>
<input type="color" id="color_picker" style="position:absolute; left:-1000px; top:-1000px; width:1px; height:1px; overflow:hidden;">
<ul class="edit_dialog" id="group_edit">
<input class="edit_dialog_edit_name text_input" id="group_edit_name" type="text"></input>
<div class="group_edit_color" id="group_edit_font"></div>
<br>
<div class="edit_dialog_discard" id="group_edit_discard"><span class="edit_dialog_button" id="group_edit_button_cancel"></span></div>
<div class="edit_dialog_confirm" id="group_edit_confirm"><span class="edit_dialog_button" id="group_edit_button_confirm"></span></div>
</ul>
<ul class="edit_dialog" id="folder_edit">
<input class="edit_dialog_edit_name text_input" id="folder_edit_name" type="text"></input>
<br>
<div class="edit_dialog_discard" id="folder_edit_discard"><span class="edit_dialog_button" id="folder_edit_button_cancel"></span></div>
<div class="edit_dialog_confirm" id="folder_edit_confirm"><span class="edit_dialog_button" id="folder_edit_button_confirm"></span></div>
</ul>
<ul class="edit_dialog" id="manager_window">
<div id="manager_window_header">
<div id="manager_window_header_title"></div>
<div id="manager_window_close">
<div class="close_img"></div>
</div>
</div>
<div id="manager_window_toolbar">
<div class="manager_window_toolbar_button mw_on" id="manager_window_groups_button">
<div class="manager_window_toolbar_button_img"></div>
</div>
<div class="manager_window_toolbar_button" id="manager_window_sessions_button">
<div class="manager_window_toolbar_button_img"></div>
</div>
<div class="manager_window_toolbar_button" id="manager_window_autosave_button">
<div class="manager_window_toolbar_button_img"></div>
</div>
</div>
<!--
<div class="manager_window_panel mw_pan_on" id="manager_window_groups_panel">
<div class="manager_window_panel_buttons">
<div class="edit_dialog_confirm" id="manager_window_button_import_group"><span class="edit_dialog_button" id="manager_window_button_label_import_group"></span></div>
<div class="edit_dialog_confirm" id="manager_window_button_hibernate_group"><span class="edit_dialog_button" id="manager_window_button_label_hibernate_group"></span></div>
</div>
<div class="manager_window_list" id="manager_window_groups_list"></div>
</div>
<div class="manager_window_panel" id="manager_window_sessions_panel">
<div class="manager_window_panel_buttons">
<div class="edit_dialog_confirm" id="manager_window_button_import_session"><span class="edit_dialog_button" id="manager_window_button_label_import_session"></span></div>
<div class="edit_dialog_confirm" id="manager_window_button_save_current_session"><span class="edit_dialog_button" id="manager_window_button_label_save_current_session"></span></div>
</div>
<div class="manager_window_list" id="manager_window_sessions_list"></div>
</div>
<div class="manager_window_panel" id="manager_window_autosave_panel">
<div class="manager_window_panel_buttons">
<span class="manager_window_label" id="manager_window_autosessions_maximum_saves_label"></span>
<br>
<input class="input_number" type="number" min="0" max="99999" step="1" id="manager_window_autosessions_maximum_saves"></input>
<br>
<span class="manager_window_label" id="manager_window_autosessions_save_timer_label"></span>
<br>
<input class="input_number" type="number" min="0" max="99999" step="1" id="manager_window_autosessions_save_timer"></input>
</div>
<div class="manager_window_list" id="manager_window_autosessions_list"></div>
</div>
</ul>
<div id="status_bar">
<div id="new_tab_floating_button_img"></div>
<div id="status_message"></div>
<div id="busy_spinner"></div>
</div>
<ul class="menu" id="main_menu"></ul>
<!--
<ul class="menu" id="move_to_group_menu">
<li data-action="move_to_new_group" class="menu_item" id="menu_detach_tab_to_new_group"></li>
<div class="separator"></div>
@ -215,28 +154,24 @@
<div id="DATA" style="display: none; width:0px; height:0px;">
</div>
-->
<script type="text/javascript" src="scripts/common.js"></script>
<script type="text/javascript" src="scripts/listeners.js"></script>
<script type="text/javascript" src="scripts/utils.js"></script>
<script type="text/javascript" src="scripts/theme.js"></script>
<script type="text/javascript" src="scripts/toolbar.js"></script>
<script type="text/javascript" src="scripts/refresh.js"></script>
<script type="text/javascript" src="scripts/backup.js"></script>
<script type="text/javascript" src="scripts/tabs.js"></script>
<script type="text/javascript" src="scripts/folders.js"></script>
<script type="text/javascript" src="scripts/groups.js"></script>
<script type="text/javascript" src="scripts/menu.js"></script>
<script type="text/javascript" src="scripts/manager.js"></script>
<script type="text/javascript" src="sidebar.js"></script>
<script type="text/javascript" src="scripts/events.js"></script>
</body>
<script type="text/javascript" src="./global.js"></script>
<script type="text/javascript" src="./scripts/utils.js"></script>
<script type="text/javascript" src="./scripts/dom.js"></script>
<script type="text/javascript" src="./scripts/tabs.js"></script>
<script type="text/javascript" src="./scripts/folders.js"></script>
<script type="text/javascript" src="./scripts/groups.js"></script>
<script type="text/javascript" src="./scripts/menu.js"></script>
<script type="text/javascript" src="./scripts/manager.js"></script>
<script type="text/javascript" src="./scripts/toolbar.js"></script>
<script type="text/javascript" src="./scripts/theme.js"></script>
<script type="text/javascript" src="./scripts/file.js"></script>
<script type="text/javascript" src="./scripts/preferences.js"></script>
<script type="text/javascript" src="./scripts/bookmark.js"></script>
<script type="text/javascript" src="./sidebar.js"></script>
</html>
</body>
</html>

View File

@ -1,37 +1,287 @@
// 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/
// SIDEBAR VARIABLES
let tt = {
CurrentWindowId: 0,
active_group: "tab_list",
tabs: {},
groups: {},
folders: {},
schedule_update_data: 0,
schedule_rearrange_tabs: 0,
document.addEventListener("DOMContentLoaded", Run(), false);
Dragging: false,
DraggingGroup: false,
DraggingPin: false,
DraggingTab: false,
DraggingFolder: false,
DragTreeDepth: 0,
DragOverId: "",
DragOverTimer: undefined,
DOMmenu: undefined,
menu: {},
menuItemNode: undefined,
SearchIndex: 0,
function Run() {
ShowStatusBar({show: true, spinner: true, message: "Starting up"});
chrome.runtime.sendMessage({command: "is_bg_ready"}, function(response) {
if (response == true) {
Initialize();
} else {
setTimeout(function() {
Run();
},100);
}
});
AutoSaveSession: undefined,
pressed_keys: []
};
function StartSidebarListeners() {
if (browserId == "F") {
browser.browserAction.onClicked.addListener(function(tab) {
if (tab.windowId == tt.CurrentWindowId) browser.sidebarAction.close();
});
}
chrome.commands.onCommand.addListener(function(command) {
if (command == "close_tree") {
chrome.windows.getCurrent({populate: false}, function(window) {
if (window.id == tt.CurrentWindowId && window.focused) {
chrome.tabs.query({windowId: tt.CurrentWindowId, active: true}, function(tabs) {
let tabsArr = [];
let close_tree = document.querySelectorAll("[id='" + tabs[0].id + "'] .tab, [id='" + tabs[0].id + "']");
for (let s of close_tree) {
tabsArr.push(parseInt(s.id));
if (s.childNodes[2].childNodes.length > 0) {
let trees_children = document.querySelectorAll("#" + s.childNodes[2].id + " .tab");
for (let t of trees_children) {
tabsArr.push(parseInt(t.id));
}
}
}
Tabs_CloseTabs(tabsArr);
});
}
});
}
});
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if (message.command == "bg_started") {
window.location.reload();
return;
}
if (message.command == "backup_available") {
if (opt.debug) Utils_log("message to sidebar " + tt.CurrentWindowId + ": message: " + message.command);
let BAKbutton = document.getElementById("button_load_bak" + message.bak);
if (BAKbutton != null) BAKbutton.classList.remove("disabled");
return;
}
if (message.command == "drag_start") {
if (opt.debug) Utils_log("message to sidebar " + tt.CurrentWindowId + ": message: " + message.command);
DOM_CleanUpDragAndDrop();
tt.DragTreeDepth = message.DragTreeDepth;
tt.DraggingGroup = message.DraggingGroup;
tt.DraggingPin = message.DraggingPin;
tt.DraggingTab = message.DraggingTab;
tt.DraggingFolder = message.DraggingFolder;
return;
}
if (message.command == "drag_end") {
if (opt.debug) Utils_log("message to sidebar " + tt.CurrentWindowId + ": message: " + message.command);
tt.Dragging = false;
DOM_CleanUpDragAndDrop();
DOM_RemoveHighlight();
return;
}
if (message.command == "remove_folder") {
if (opt.debug) Utils_log("message to sidebar " + tt.CurrentWindowId + ": message: " + message.command + " folderId: " + message.folderId);
Folders_RemoveFolder(message.folderId);
return;
}
if (message.command == "remove_group") {
if (opt.debug) Utils_log("message to sidebar " + tt.CurrentWindowId + ": message: " + message.command + " groupId: " + message.groupId);
setTimeout(function() {Groups_GroupRemove(message.groupId, false);}, 2000);
return;
}
if (message.command == "reload_sidebar") {
if (opt.debug) Utils_log("message to sidebar " + tt.CurrentWindowId + ": message: " + message.command);
window.location.reload();
return;
}
if (message.command == "reload_options") {
if (opt.debug) Utils_log("message to sidebar " + tt.CurrentWindowId + ": message: " + message.command);
opt = Object.assign({}, message.opt);
setTimeout(function() {
Theme_RestorePinListRowSettings();
}, 100);
return;
}
if (message.command == "reload_toolbar") {
if (opt.debug) Utils_log("message to sidebar " + tt.CurrentWindowId + ": message: " + message.command);
opt = Object.assign({}, message.opt);
if (opt.show_toolbar) {
Toolbar_RemoveToolbar();
Toolbar_RecreateToolbar(message.toolbar);
Toolbar_SetToolbarEvents(false, true, true, "mousedown", true);
Toolbar_RestoreToolbarShelf();
Toolbar_RestoreToolbarSearchFilter();
} else {
Toolbar_RemoveToolbar();
}
DOM_RefreshGUI();
return;
}
if (message.command == "reload_theme") {
if (opt.debug) Utils_log("message to sidebar " + tt.CurrentWindowId + ": message: " + message.command);
Theme_RestorePinListRowSettings();
Theme_ApplyTheme(message.theme);
return;
}
if (message.windowId == tt.CurrentWindowId) {
if (message.command == "tab_created") {
if (message.InsertAfterId && document.querySelectorAll("#" + tt.active_group + " .tab").length == 0) {
message.InsertAfterId = undefined;
message.ParentId = tt.active_group;
}
tt.tabs[message.tabId] = new Tabs_ttTab({tab: message.tab, ParentId: message.ParentId, InsertAfterId: message.InsertAfterId, Append: message.Append, Scroll: true});
DOM_RefreshExpandStates();
setTimeout(function() {
DOM_RefreshCounters();
DOM_RefreshGUI();
}, 50);
if (opt.syncro_tabbar_tabs_order) {
let tabIds = Array.prototype.map.call(document.querySelectorAll(".pin, .tab"), function(s) {return parseInt(s.id);});
chrome.tabs.move(message.tab.id, {index: tabIds.indexOf(message.tab.id)});
}
setTimeout(function() {tt.schedule_update_data++;}, 2000);
return;
}
if (message.command == "tab_attached") {
if (opt.debug) Utils_log("chrome event: " + message.command + ", tabId: " + message.tabId + ", tab is pinned: " + message.tab.pinned + ", ParentId: " + message.ParentId);
tt.tabs[message.tabId] = new Tabs_ttTab({tab: message.tab, ParentId: message.ParentId, Append: true, SkipSetActive: false, SkipMediaIcon: false});
DOM_RefreshGUI();
return;
}
if (message.command == "tab_detached") {
if (opt.debug) Utils_log("chrome event: " + message.command + ", tabId: " + message.tabId);
let Tab = document.getElementById(message.tabId);
if (Tab != null && tt.tabs[message.tabId]) {
let ctDetachedParent = Tab.childNodes[1];
if (opt.promote_children_in_first_child == true && Tab.childNodes[1].childNodes.length > 1) {
DOM_PromoteChildrenToFirstChild(Tab);
} else {
while (ctDetachedParent.firstChild) {
ctDetachedParent.parentNode.parentNode.insertBefore(ctDetachedParent.firstChild, ctDetachedParent.parentNode);
}
}
}
tt.tabs[message.tabId].RemoveTab();
setTimeout(function() {tt.schedule_update_data++;}, 300);
DOM_RefreshGUI();
return;
}
if (message.command == "tab_removed") {
if (opt.debug) {Utils_log("chrome event: " + message.command + ", tabId: " + message.tabId);}
let mTab = document.getElementById(message.tabId);
if (mTab != null && tt.tabs[message.tabId]) {
let ctParent = mTab.childNodes[1];
if (opt.debug) Utils_log("tab_removed, promote children: " + opt.promote_children);
if (opt.promote_children == true) {
if (opt.promote_children_in_first_child == true && mTab.childNodes[1].childNodes.length > 1) {
DOM_PromoteChildrenToFirstChild(mTab);
} else {
while (ctParent.firstChild) {
ctParent.parentNode.parentNode.insertBefore(ctParent.firstChild, ctParent.parentNode);
}
}
} else {
let tab_children = document.querySelectorAll("[id='" + message.tabId + "'] .tab");
for (let s of tab_children) {
chrome.tabs.remove(parseInt(s.id));
}
}
tt.tabs[message.tabId].RemoveTab();
DOM_RefreshExpandStates();
setTimeout(function() {tt.schedule_update_data++;}, 300);
DOM_RefreshGUI();
DOM_RefreshCounters();
}
return;
}
if (message.command == "tab_activated") {
if (opt.debug) Utils_log("chrome event: " + message.command + ", tabId: " + message.tabId);
Tabs_SetActiveTab(message.tabId, true);
return;
}
if (message.command == "tab_attention") {
if (opt.debug) Utils_log("chrome event: " + message.command + ", tabId: " + message.tabId);
if (tt.tabs[message.tabId]) tt.tabs[message.tabId].SetAttentionIcon();
return;
}
if (message.command == "tab_updated") {
if (opt.debug) Utils_log("chrome event: " + message.command + ", tabId: " + message.tabId);
if (tt.tabs[message.tabId]) {
if (message.changeInfo.favIconUrl != undefined || message.changeInfo.url != undefined) {
if (browserId == "F" && (message.changeInfo.favIconUrl == undefined || message.changeInfo.favIconUrl == "")) browser.sessions.setTabValue(message.tabId, "CachedFaviconUrl", "");
setTimeout(function() {
if (tt.tabs[message.tabId]) tt.tabs[message.tabId].GetFaviconAndTitle(true);
}, 100);
}
if (message.changeInfo.title != undefined) {
setTimeout(function() {
if (tt.tabs[message.tabId]) tt.tabs[message.tabId].GetFaviconAndTitle(true);
}, 1000);
}
if (message.changeInfo.audible != undefined || message.changeInfo.mutedInfo != undefined) tt.tabs[message.tabId].RefreshMediaIcon();
if (message.changeInfo.discarded != undefined) tt.tabs[message.tabId].RefreshDiscarded();
if (message.changeInfo.pinned != undefined) {
let updateTab = document.getElementById(message.tabId);
if (updateTab != null) {
if (message.tab.pinned && updateTab.classList.contains("pin") == false) {
tt.tabs[message.tabId].SetTabClass(true);
tt.tabs[message.tabId].pinned = true;
tt.schedule_update_data++;
}
if (!message.tab.pinned && updateTab.classList.contains("tab") == false) {
tt.tabs[message.tabId].SetTabClass(false);
tt.tabs[message.tabId].pinned = false;
tt.schedule_update_data++;
}
}
DOM_RefreshExpandStates();
}
}
return;
}
// if (message.command == "set_active_group") {
// Groups_SetActiveGroup(message.groupId, false, false);
// return;
// }
if (message.command == "remote_update") {
if (opt.debug) {
Utils_log("chrome event: " + message.command + ", tabId: " + message.tabId);
Utils_log(message);
}
Manager_RecreateTreeStructure(message.groups, message.folders, message.tabs);
sendResponse(true);
tt.schedule_update_data++;
return;
}
if (message.command == "switch_active_tab") {
Tabs_SwitchActiveTabBeforeClose(tt.active_group);
return;
}
}
});
}
function Initialize() {
chrome.windows.getCurrent({populate: true}, function(window) {
tt.CurrentWindowId = window.id;
let tabs = window.tabs;
chrome.storage.local.get(null, function(storage) {
GetCurrentPreferences(storage);
ApplyTheme(GetCurrentTheme(storage));
Preferences_GetCurrentPreferences(storage);
Menu_CreateMenu();
Theme_ApplyTheme(Theme_GetCurrentTheme(storage));
if (opt.show_toolbar) {
RecreateToolbar(GetCurrentToolbar(storage));
SetToolbarEvents(false, true, true, "mousedown");
RestoreToolbarShelf();
RestoreToolbarSearchFilter();
Toolbar_RecreateToolbar(Theme_GetCurrentToolbar(storage));
Toolbar_SetToolbarEvents(false, true, true, "mousedown", true, false);
Toolbar_RestoreToolbarShelf();
Toolbar_RestoreToolbarSearchFilter();
}
chrome.runtime.sendMessage({command: "get_browser_tabs"}, function(bgtabs) {
@ -40,62 +290,65 @@ function Initialize() {
chrome.runtime.sendMessage({command: "get_groups", windowId: tt.CurrentWindowId}, function(g) {
tt.groups = Object.assign({}, g);
// APPEND GROUPS
AppendGroups(tt.groups);
// APPEND FOLDERS
AppendFolders(tt.folders);
// APPEND TABS
let ti = 0;
let tc = tabs.length;
let ttTabs = [];
for (ti = 0; ti < tc; ti++) {
ttTabs.push(AppendTab({ tab: tabs[ti], Append: true, SkipSetActive: true, AdditionalClass: (bgtabs[tabs[ti].id].expand != "" ? bgtabs[tabs[ti].id].expand : undefined) }));
Groups_AppendGroups(tt.groups);
// APPEND FOLDERS TO TABLIST
Folders_PreAppendFolders(tt.folders);
// APPEND TABS TO TABLIST
for (const tab of window.tabs) {
tt.tabs[tab.id] = new Tabs_ttTab({tab: tab, Append: true, SkipSetActive: true, AdditionalClass: ((bgtabs[tab.id] && bgtabs[tab.id].expand != "") ? bgtabs[tab.id].expand : undefined)});
}
// APPEND FOLDERS TO CORRECT PARENTS
Folders_AppendFolders(tt.folders);
// APPEND TABS TO CORRECT PARENTS
if (opt.skip_load == false) {
for (ti = 0; ti < tc; ti++) {
if (bgtabs[tabs[ti].id] && !tabs[ti].pinned) {
let TabParent = document.getElementById("ct"+bgtabs[tabs[ti].id].parent);
if (TabParent != null && document.querySelector("[id='"+tabs[ti].id+"'] #ct"+bgtabs[tabs[ti].id].parent) == null) {
TabParent.appendChild(ttTabs[ti]);
for (const tab of window.tabs) {
if (bgtabs[tab.id] && !tab.pinned) {
let TabParent = document.getElementById("°"+bgtabs[tab.id].parent);
if (TabParent != null && document.querySelector("[id='"+tab.id+"'] #°"+bgtabs[tab.id].parent) == null) {
TabParent.appendChild(tt.tabs[tab.id].Node);
}
}
}
}
// SET ACTIVE TAB FOR EACH GROUP, REARRENGE EVERYTHING AND START BROWSER LISTENERS
SetActiveTabInEachGroup();
RearrangeFolders(true);
RearrangeTreeTabs(bgtabs, true);
Groups_SetActiveTabInEachGroup();
Tabs_RearrangeTree(bgtabs, tt.folders, true);
StartSidebarListeners();
SetMenu();
SetEvents();
SetManagerEvents();
HideMenus();
DOM_SetEvents();
Manager_SetManagerEvents();
Menu_HideMenus();
if (opt.switch_with_scroll) {
BindTabsSwitchingToMouseWheel("pin_list");
DOM_BindTabsSwitchingToMouseWheel("pin_list");
}
if (opt.syncro_tabbar_tabs_order || opt.syncro_tabbar_groups_tabs_order) {
RearrangeBrowserTabs();
Tabs_RearrangeBrowserTabs();
}
RestorePinListRowSettings();
StartAutoSaveSession();
if (browserId == "V") {
VivaldiRefreshMediaIcons();
Theme_RestorePinListRowSettings();
Manager_StartAutoSaveSession();
if (browserId == "O") {
DOM_AutoRefreshMediaIcons();
}
setTimeout(function() {
RefreshExpandStates();
RefreshCounters();
SetActiveTabInEachGroup();
if (browserId == "F" && opt.skip_load == false && storage.emergency_reload == undefined) {
RecheckFirefox();
}
DOM_RefreshExpandStates();
DOM_RefreshCounters();
Groups_SetActiveTabInEachGroup();
}, 1000);
ShowStatusBar({show: true, spinner: false, message: "Ready.", hideTimeout: 2000});
Manager_ShowStatusBar({show: true, spinner: false, message: "Ready.", hideTimeout: 2000});
setTimeout(function() {
UpdateData();
delete b;
Tabs_SaveTabs();
delete DefaultToolbar;
delete DefaultTheme;
delete DefaultPreferences;
@ -103,6 +356,7 @@ function Initialize() {
chrome.storage.local.remove("emergency_reload");
}
}, 5000);
if (browserId != "F") {
if (storage.windows_BAK1 && Object.keys(storage["windows_BAK1"]).length > 0 && document.getElementById("button_load_bak1") != null) { document.getElementById("button_load_bak1").classList.remove("disabled"); }
if (storage.windows_BAK2 && Object.keys(storage["windows_BAK2"]).length > 0 && document.getElementById("button_load_bak2") != null) { document.getElementById("button_load_bak2").classList.remove("disabled"); }
@ -114,3 +368,18 @@ function Initialize() {
});
});
}
function Run() {
Manager_ShowStatusBar({show: true, spinner: true, message: "Starting up"});
chrome.runtime.sendMessage({command: "is_bg_ready"}, function(response) {
if (response == true) {
Initialize();
} else {
setTimeout(function() {
Run();
},100);
}
});
}
document.addEventListener("DOMContentLoaded", Run(), false);

View File

@ -499,11 +499,7 @@ div {
overflow-y: auto;
}
.group>.children_folders {
position: relative;
top: var(--group_folders_top);
}
.group>.children_tabs {
.group>.children {
position: relative;
top: var(--group_tabs_top);
}
@ -582,295 +578,8 @@ div {
}
/* PINS AND TABS COLORS, WATCH OUT AND DON'T MESS WITH IT */
/* normal */
.tab_header{
border-radius:var(--tab_header_border_radius);
border:1px solid var(--tab_border);
background-color:var(--tab_background);
}
.tab>.tab_header>.tab_title{
color:var(--tab_title_font_color);
font-style:var(--tab_title_font_style);
font-weight:var(--tab_title_font_weight);
}
/* normal hover */
.tab_header_hover{
border-radius:var(--tab_header_border_radius);
border:1px solid var(--tab_hover_border);
background-color:var(--tab_hover_background);
}
.tab>.tab_header_hover>.tab_title{
color:var(--tab_hover_title_font_color);
font-style:var(--tab_hover_title_font_style);
font-weight:var(--tab_hover_title_font_weight);
}
/* normal selected */
.selected_tab>.tab_header{
border:1px solid var(--tab_selected_border);
background-color:var(--tab_selected_background);
}
.tab.selected_tab>.tab_header>.tab_title{
color:var(--tab_selected_title_font_color);
font-style:var(--tab_selected_title_font_style);
font-weight:var(--tab_selected_title_font_weight);
}
/* normal selected hover */
.selected_tab>.tab_header_hover{
border:1px solid var(--tab_selected_hover_border);
background-color:var(--tab_selected_hover_background);
}
.tab.selected_tab>.tab_header_hover>.tab_title{
color:var(--tab_selected_hover_title_font_color);
font-style:var(--tab_selected_hover_title_font_style);
font-weight:var(--tab_selected_hover_title_font_weight);
}
/* normal active */
.active_tab>.tab_header{
border:1px solid var(--tab_active_border);
background-color:var(--tab_active_background);
}
.tab.active_tab>.tab_header>.tab_title{
color:var(--tab_active_title_font_color);
font-style:var(--tab_active_title_font_style);
font-weight:var(--tab_active_title_font_weight);
}
/* normal active hover */
.active_tab>.tab_header_hover{
border:1px solid var(--tab_active_hover_border);
background-color:var(--tab_active_hover_background);
}
.tab.active_tab>.tab_header_hover>.tab_title{
color:var(--tab_active_hover_title_font_color);
font-style:var(--tab_active_hover_title_font_style);
font-weight:var(--tab_active_hover_title_font_weight);
}
/* normal selected active */
.selected_tab.active_tab>.tab_header{
border:1px solid var(--tab_active_selected_border);
background-color:var(--tab_active_selected_background);
}
.tab.selected_tab.active_tab>.tab_header>.tab_title{
color:var(--tab_active_selected_title_font_color);
font-style:var(--tab_active_selected_title_font_style);
font-weight:var(--tab_active_selected_title_font_weight);
}
/* normal selected active hover */
.selected_tab.active_tab>.tab_header_hover{
border:1px solid var(--tab_selected_active_hover_border);
background-color:var(--tab_selected_active_hover_background);
}
.tab.selected_tab.active_tab>.tab_header_hover>.tab_title{
color:var(--tab_selected_active_hover_title_font_color);
font-style:var(--tab_selected_active_hover_title_font_style);
font-weight:var(--tab_selected_active_hover_title_font_weight);
}
/* unloaded */
.discarded>.tab_header{
border:1px solid var(--tab_discarded_border);
background-color:var(--tab_discarded_background);
}
.tab.discarded>.tab_header>.tab_title{
color:var(--tab_discarded_title_font_color);
font-style:var(--tab_discarded_title_font_style);
font-weight:var(--tab_discarded_title_font_weight);
}
/* unloaded hover */
.discarded>.tab_header_hover{
border:1px solid var(--tab_discarded_hover_border);
background-color:var(--tab_discarded_hover_background);
}
.tab.discarded>.tab_header_hover>.tab_title{
color:var(--tab_discarded_hover_title_font_color);
font-style:var(--tab_discarded_hover_title_font_style);
font-weight:var(--tab_discarded_hover_title_font_weight);
}
/* unloaded selected */
.selected_tab.discarded>.tab_header{
border:1px solid var(--tab_selected_discarded_border);
background-color:var(--tab_selected_discarded_background);
}
.tab.selected_tab.discarded>.tab_header>.tab_title{
color:var(--tab_selected_discarded_title_font_color);
font-style:var(--tab_selected_discarded_title_font_style);
font-weight:var(--tab_selected_discarded_title_font_weight);
}
/* unloaded selected hover */
.selected_tab.discarded>.tab_header_hover{
border:1px solid var(--tab_selected_discarded_hover_border);
background-color:var(--tab_selected_discarded_hover_background);
}
.tab.selected_tab.discarded>.tab_header_hover>.tab_title{
color:var(--tab_selected_discarded_hover_title_font_color);
font-style:var(--tab_selected_discarded_hover_title_font_style);
font-weight:var(--tab_selected_discarded_hover_title_font_weight);
}
/* search result */
.filtered>.tab_header{
border:1px solid var(--tab_filtered_border);
background-color:var(--tab_filtered_background);
}
.tab.filtered>.tab_header>.tab_title{
color:var(--tab_filtered_title_font_color);
font-style:var(--tab_filtered_title_font_style);
font-weight:var(--tab_filtered_title_font_weight);
}
/* search result hover */
.filtered>.tab_header_hover{
border:1px solid var(--tab_filtered_hover_border);
background-color:var(--tab_filtered_hover_background);
}
.tab.filtered>.tab_header_hover>.tab_title{
color:var(--tab_filtered_hover_title_font_color);
font-style:var(--tab_filtered_hover_title_font_style);
font-weight:var(--tab_filtered_hover_title_font_weight);
}
/* search result active */
.filtered.active_tab>.tab_header{
border:1px solid var(--tab_filtered_active_border);
background-color:var(--tab_filtered_active_background);
}
.tab.filtered.active_tab>.tab_header>.tab_title{
color:var(--tab_filtered_active_title_font_color);
font-style:var(--tab_filtered_active_title_font_style);
font-weight:var(--tab_filtered_active_title_font_weight);
}
/* search result active hover */
.filtered.active_tab>.tab_header_hover{
border:1px solid var(--tab_filtered_active_hover_border);
background-color:var(--tab_filtered_active_hover_background);
}
.tab.filtered.active_tab>.tab_header_hover>.tab_title{
color:var(--tab_filtered_active_hover_title_font_color);
font-style:var(--tab_filtered_active_hover_title_font_style);
font-weight:var(--tab_filtered_active_hover_title_font_weight);
}
/* search result selected */
.selected_tab.filtered>.tab_header{
border:1px solid var(--tab_filtered_selected_border);
background-color:var(--tab_filtered_selected_background);
}
.tab.selected_tab.filtered>.tab_header>.tab_title{
color:var(--tab_filtered_selected_title_font_color);
font-style:var(--tab_filtered_selected_title_font_style);
font-weight:var(--tab_filtered_selected_title_font_weight);
}
/* search result selected hover */
.selected_tab.filtered>.tab_header_hover{
border:1px solid var(--tab_filtered_selected_hover_border);
background-color:var(--tab_filtered_selected_hover_background);
}
.tab.selected_tab.filtered>.tab_header_hover>.tab_title{
color:var(--tab_filtered_selected_hover_title_font_color);
font-style:var(--tab_filtered_selected_hover_title_font_style);
font-weight:var(--tab_filtered_selected_hover_title_font_weight);
}
/* search result active selected */
.selected_tab.filtered.active_tab>.tab_header{
border:1px solid var(--tab_filtered_selected_active_border);
background-color:var(--tab_filtered_selected_active_background);
}
.tab.selected_tab.filtered.active_tab>.tab_header>.tab_title{
color:var(--tab_filtered_selected_active_title_font_color);
font-style:var(--tab_filtered_selected_active_title_font_style);
font-weight:var(--tab_filtered_selected_active_title_font_weight);
}
/* search result active selected hover */
.selected_tab.filtered.active_tab>.tab_header_hover{
border:1px solid var(--tab_filtered_selected_active_hover_border);
background-color:var(--tab_filtered_selected_active_hover_background);
}
.tab.filtered.selected_tab.active_tab>.tab_header_hover>.tab_title{
color:var(--tab_filtered_selected_active_hover_title_font_color);
font-style:var(--tab_filtered_selected_active_hover_title_font_style);
font-weight:var(--tab_filtered_selected_active_hover_title_font_weight);
}
/* search result highlighted */
.filtered.highlighted_search>.tab_header{
border:1px solid var(--tab_filtered_highlighted_search_border);
background-color:var(--tab_filtered_highlighted_search_background);
}
.tab.filtered.highlighted_search>.tab_header>.tab_title{
color:var(--tab_filtered_highlighted_search_title_font_color);
font-style:var(--tab_filtered_highlighted_search_title_font_style);
font-weight:var(--tab_filtered_highlighted_search_title_font_weight);
}
/* search result highlighted hover */
.filtered.highlighted_search>.tab_header_hover{
border:1px solid var(--tab_filtered_highlighted_search_hover_border);
background-color:var(--tab_filtered_highlighted_search_hover_background);
}
.tab.filtered.highlighted_search>.tab_header_hover>.tab_title{
color:var(--tab_filtered_highlighted_search_hover_title_font_color);
font-style:var(--tab_filtered_highlighted_search_hover_title_font_style);
font-weight:var(--tab_filtered_highlighted_search_hover_title_font_weight);
}
/* search result active highlighted */
.active_tab.filtered.highlighted_search>.tab_header{
border:1px solid var(--tab_filtered_active_highlighted_search_border);
background-color:var(--tab_filtered_active_highlighted_search_background);
}
.tab.active_tab.filtered.highlighted_search>.tab_header>.tab_title{
color:var(--tab_filtered_active_highlighted_search_title_font_color);
font-style:var(--tab_filtered_active_highlighted_search_title_font_style);
font-weight:var(--tab_filtered_active_highlighted_search_title_font_weight);
}
/* search result active highlighted hover */
.active_tab.filtered.highlighted_search>.tab_header_hover{
border:1px solid var(--tab_filtered_active_highlighted_search_hover_border);
background-color:var(--tab_filtered_active_highlighted_search_hover_background);
}
.tab.active_tab.filtered.highlighted_search>.tab_header_hover>.tab_title{
color:var(--tab_filtered_active_highlighted_search_hover_title_font_color);
font-style:var(--tab_filtered_active_highlighted_search_hover_title_font_style);
font-weight:var(--tab_filtered_active_highlighted_search_hover_title_font_weight);
}
/* search result selected highlighted */
.selected_tab.filtered.highlighted_search>.tab_header{
border:1px solid var(--tab_filtered_selected_highlighted_search_border);
background-color:var(--tab_filtered_selected_highlighted_search_background);
}
.tab.selected_tab.filtered.highlighted_search>.tab_header>.tab_title{
color:var(--tab_filtered_selected_highlighted_search_title_font_color);
font-style:var(--tab_filtered_selected_highlighted_search_title_font_style);
font-weight:var(--tab_filtered_selected_highlighted_search_title_font_weight);
}
/* search result selected highlighted hover */
.selected_tab.filtered.highlighted_search>.tab_header_hover{
border:1px solid var(--tab_filtered_selected_highlighted_search_hover_border);
background-color:var(--tab_filtered_selected_highlighted_search_hover_background);
}
.tab.selected_tab.filtered.highlighted_search>.tab_header_hover>.tab_title{
color:var(--tab_filtered_selected_highlighted_search_hover_title_font_color);
font-style:var(--tab_filtered_selected_highlighted_search_hover_title_font_style);
font-weight:var(--tab_filtered_selected_highlighted_search_hover_title_font_weight);
}
/* search result selected active highlighted */
.active_tab.selected_tab.filtered.highlighted_search>.tab_header{
border:1px solid var(--tab_filtered_selected_active_highlighted_search_border);
background-color:var(--tab_filtered_selected_active_highlighted_search_background);
}
.tab.active_tab.selected_tab.filtered.highlighted_search>.tab_header>.tab_title{
color:var(--tab_filtered_selected_active_highlighted_search_title_font_color);
font-style:var(--tab_filtered_selected_active_highlighted_search_title_font_style);
font-weight:var(--tab_filtered_selected_active_highlighted_search_title_font_weight);
}
/* search result selected active highlighted hover */
.active_tab.selected_tab.filtered.highlighted_search>.tab_header_hover{
border:1px solid var(--tab_filtered_selected_active_highlighted_search_hover_border);
background-color:var(--tab_filtered_selected_active_highlighted_search_hover_background);
}
.tab.active_tab.selected_tab.filtered.highlighted_search>.tab_header_hover>.tab_title{
color:var(--tab_filtered_selected_active_highlighted_search_hover_title_font_color);
font-style:var(--tab_filtered_selected_active_highlighted_search_hover_title_font_style);
font-weight:var(--tab_filtered_selected_active_highlighted_search_hover_title_font_weight);
}
/* TABS */
/* regular tab title */
.tab_title {
z-index: 5;
@ -883,6 +592,7 @@ div {
padding-left: var(--tab_title_text_padding_left);
font-size: var(--title_font_size);
pointer-events: none;
line-height: var(--tab_height);
}
.tab {
@ -904,7 +614,7 @@ div {
top: 0px;
left: 0px;
height: var(--tab_height);
line-height: var(--tab_height_line);
/* line-height: var(--tab_height_line); */
width: calc(100% - 2px);
background-image: url(../theme/icon_empty.svg);
background-size: var(--favicon_width) var(--favicon_height);
@ -912,7 +622,7 @@ div {
/* background-image: linear-gradient(to bottom, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.6) 100%), url(../theme/icon_empty.svg); */
}
.group>.children_tabs>:last-child {
.group>.children>:last-child {
margin-bottom: 16px;
}
@ -934,19 +644,19 @@ div {
}
/* CHILDREN TABS */
.tab>.children_tabs {
.tab>.children {
position: relative;
padding-left: var(--children_padding_left);
}
.tab>.children_tabs>.tab {
.tab>.children>.tab {
margin-right: 0px;
}
.tab.o>.children_tabs {
.tab.o>.children {
height: auto;
}
.tab.c>.children_tabs {
.tab.c>.children {
display: none;
height: 0px;
}
@ -980,7 +690,6 @@ div {
}
/* FOLDERS */
.folder_title {
z-index: 5;
font-family: Arial, Helvetica, "Nimbus Sans L", "Liberation Sans", FreeSans, Sans-serif;
@ -991,10 +700,12 @@ div {
padding-right: 3px;
padding-left: var(--tab_title_text_padding_left);
font-size: var(--title_font_size);
pointer-events: none;
line-height: var(--tab_height);
/* colors and styles */
color:var(--tab_title_font_color);
font-style:var(--tab_title_font_style);
font-weight:var(--tab_title_font_weight);
pointer-events: none;
}
.folder {
@ -1014,32 +725,29 @@ div {
top: 0px;
left: 0px;
height: var(--tab_height);
line-height: var(--tab_height_line);
/* line-height: var(--tab_height_line); */
width: calc(100% - 2px);
border-radius:var(--tab_header_border_radius);
border:1px solid var(--tab_border);
background-color:var(--tab_background);
border-radius: var(--tab_header_border_radius);
border: 1px solid var(--tab_border);
background-color: var(--tab_background);
}
.folder>.children_folders,
.folder>.children_tabs {
.folder>.children {
position: relative;
padding-left: var(--children_padding_left);
}
.folder>.children_folders>.folder,
.folder>.children_tabs>.tab {
.folder>.children>.folder,
.folder>.children>.tab {
margin-right: 0px;
}
.folder.o>.children_folders,
.folder.o>.children_tabs {
.folder.o>.children {
height: auto;
}
.folder.c>.children_folders,
.folder.c>.children_tabs {
.folder.c>.children {
display: none;
height: 0px;
}
@ -1079,36 +787,7 @@ div {
mask-image: url(../theme/icon_folder_open.svg);
}
/* normal hover */
.folder>.folder_header_hover{
border-radius:var(--tab_header_border_radius);
border:1px solid var(--tab_hover_border);
background-color:var(--tab_hover_background);
}
/* normal selected */
.selected_folder>.folder_header{
border:1px solid var(--tab_selected_border);
background-color:var(--tab_selected_background);
}
.selected_folder>.folder_header>.folder_title{
color:var(--tab_selected_title_font_color);
font-style:var(--tab_selected_title_font_style);
font-weight:var(--tab_selected_title_font_weight);
}
/* normal selected hover */
.selected_folder>.folder_header_hover{
border:1px solid var(--tab_selected_hover_border);
background-color:var(--tab_selected_hover_background);
}
.selected_folder>.folder_header_hover>.folder_title{
color:var(--tab_selected_hover_title_font_color);
font-style:var(--tab_selected_hover_title_font_style);
font-weight:var(--tab_selected_hover_title_font_weight);
}
.selected_folder>.folder_header
.selected>.folder_header
.active_folder>.folder_header {
z-index: 900;
}
@ -1119,15 +798,6 @@ div {
/* PINS */
@keyframes blinking {
0% {background-color: var(--tab_background); border:1px solid var(--tab_border);}
50% {background-color: var(--attention_background); border:1px solid var(--attention_border);}
80% {background-color: var(--tab_background); border:1px solid var(--tab_border);}
100% {background-color: var(--tab_background); border:1px solid var(--tab_border);}
}
.pin.attention>.tab_header {
animation: blinking 2.5s infinite;
}
.pin {
/* pin size is here, all the rest is automatically calculated */
position: relative;
@ -1163,7 +833,7 @@ div {
background-position: center, center;
}
.pin>.children_tabs {
.pin>.children {
display: none;
position: absolute;
top: 0px;
@ -1171,7 +841,7 @@ div {
width: 0px;
}
.pin.selected_tab,
.pin.selected,
.pin.active_tab {
z-index: 800;
}
@ -1179,8 +849,10 @@ div {
margin-right: var(--pin_last_margin_right);
}
.pin.attention>.tab_header {
background-color: var(--attention_background);
border: 1px solid var(--attention_border);
}
/* DRAG AND DROP TARGETS */
@ -1244,7 +916,8 @@ div {
}
.group.highlighted_drop_target>.children_tabs>.tab:last-child>.drag_indicator,
.group.highlighted_drop_target>.children>.tab:last-child>.drag_indicator,
.group.highlighted_drop_target>.children>.folder:last-child>.drag_indicator,
.folder.highlighted_drop_target.after>.drag_indicator,
.tab.highlighted_drop_target.after>.drag_indicator {
display: block;
@ -1257,8 +930,342 @@ div {
}
.group>.children_tabs>.tab:first-child>.drag_indicator,
.group>.children_folders>.folder:first-child>.drag_indicator {
/* PINS FOLDERS AND TABS COLORS, WATCH OUT AND DON'T MESS WITH IT */
/* normal */
.folder_header.folder_header_hover,
.tab_header.tab_header_hover {
z-index: 9999;
}
.tab_header {
border-radius:var(--tab_header_border_radius);
border:1px solid var(--tab_border);
background-color:var(--tab_background);
}
.tab>.tab_header>.tab_title {
color:var(--tab_title_font_color);
font-style:var(--tab_title_font_style);
font-weight:var(--tab_title_font_weight);
}
/* normal hover */
.folder_header.folder_header_hover,
.tab_header.tab_header_hover {
border-radius:var(--tab_header_border_radius);
border:1px solid var(--tab_hover_border);
background-color:var(--tab_hover_background);
}
.folder>.folder_header_hover>.folder_title,
.tab>.tab_header_hover>.tab_title {
color:var(--tab_hover_title_font_color);
font-style:var(--tab_hover_title_font_style);
font-weight:var(--tab_hover_title_font_weight);
}
/* normal selected */
.folder.selected>.folder_header,
.pin.selected>.tab_header,
.tab.selected>.tab_header {
border:1px solid var(--tab_selected_border);
background-color:var(--tab_selected_background);
}
/* selected header title */
.folder.selected>.folder_header>.folder_title,
.tab.selected>.tab_header>.tab_title {
color:var(--tab_selected_title_font_color);
font-style:var(--tab_selected_title_font_style);
font-weight:var(--tab_selected_title_font_weight);
}
/* normal selected hover */
.folder.selected>.folder_header_hover,
.pin.selected>.tab_header_hover,
.tab.selected>.tab_header_hover {
border:1px solid var(--tab_selected_hover_border);
background-color:var(--tab_selected_hover_background);
}
.folder.selected>.folder_header_hover>.folder_title,
.tab.selected>.tab_header_hover>.tab_title {
color:var(--tab_selected_hover_title_font_color);
font-style:var(--tab_selected_hover_title_font_style);
font-weight:var(--tab_selected_hover_title_font_weight);
}
/* normal active */
.pin.active_tab>.tab_header,
.tab.active_tab>.tab_header {
border:1px solid var(--tab_active_border);
background-color:var(--tab_active_background);
}
.tab.active_tab>.tab_header>.tab_title {
color:var(--tab_active_title_font_color);
font-style:var(--tab_active_title_font_style);
font-weight:var(--tab_active_title_font_weight);
}
/* normal active hover */
.pin.active_tab>.tab_header_hover,
.tab.active_tab>.tab_header_hover {
border:1px solid var(--tab_active_hover_border);
background-color:var(--tab_active_hover_background);
}
.tab.active_tab>.tab_header_hover>.tab_title {
color:var(--tab_active_hover_title_font_color);
font-style:var(--tab_active_hover_title_font_style);
font-weight:var(--tab_active_hover_title_font_weight);
}
/* normal selected active */
.pin.selected.active_tab>.tab_header,
.tab.selected.active_tab>.tab_header {
border:1px solid var(--tab_active_selected_border);
background-color:var(--tab_active_selected_background);
}
.tab.selected.active_tab>.tab_header>.tab_title {
color:var(--tab_active_selected_title_font_color);
font-style:var(--tab_active_selected_title_font_style);
font-weight:var(--tab_active_selected_title_font_weight);
}
/* normal selected active hover */
.pin.selected.active_tab>.tab_header_hover,
.tab.selected.active_tab>.tab_header_hover {
border:1px solid var(--tab_selected_active_hover_border);
background-color:var(--tab_selected_active_hover_background);
}
.tab.selected.active_tab>.tab_header_hover>.tab_title {
color:var(--tab_selected_active_hover_title_font_color);
font-style:var(--tab_selected_active_hover_title_font_style);
font-weight:var(--tab_selected_active_hover_title_font_weight);
}
/* unloaded */
.pin.discarded>.tab_header,
.tab.discarded>.tab_header {
border:1px solid var(--tab_discarded_border);
background-color:var(--tab_discarded_background);
}
.tab.discarded>.tab_header>.tab_title {
color:var(--tab_discarded_title_font_color);
font-style:var(--tab_discarded_title_font_style);
font-weight:var(--tab_discarded_title_font_weight);
}
/* unloaded hover */
.pin.discarded>.tab_header_hover,
.tab.discarded>.tab_header_hover {
border:1px solid var(--tab_discarded_hover_border);
background-color:var(--tab_discarded_hover_background);
}
.tab.discarded>.tab_header_hover>.tab_title {
color:var(--tab_discarded_hover_title_font_color);
font-style:var(--tab_discarded_hover_title_font_style);
font-weight:var(--tab_discarded_hover_title_font_weight);
}
/* unloaded selected */
.pin.selected.discarded>.tab_header,
.tab.selected.discarded>.tab_header {
border:1px solid var(--tab_selected_discarded_border);
background-color:var(--tab_selected_discarded_background);
}
.tab.selected.discarded>.tab_header>.tab_title {
color:var(--tab_selected_discarded_title_font_color);
font-style:var(--tab_selected_discarded_title_font_style);
font-weight:var(--tab_selected_discarded_title_font_weight);
}
/* unloaded selected hover */
.pin.selected.discarded>.tab_header_hover,
.tab.selected.discarded>.tab_header_hover {
border:1px solid var(--tab_selected_discarded_hover_border);
background-color:var(--tab_selected_discarded_hover_background);
}
.tab.selected.discarded>.tab_header_hover>.tab_title {
color:var(--tab_selected_discarded_hover_title_font_color);
font-style:var(--tab_selected_discarded_hover_title_font_style);
font-weight:var(--tab_selected_discarded_hover_title_font_weight);
}
/* search result */
.pin.filtered>.tab_header,
.tab.filtered>.tab_header {
border:1px solid var(--tab_filtered_border);
background-color:var(--tab_filtered_background);
}
.tab.filtered>.tab_header>.tab_title {
color:var(--tab_filtered_title_font_color);
font-style:var(--tab_filtered_title_font_style);
font-weight:var(--tab_filtered_title_font_weight);
}
/* search result hover */
.pin.filtered>.tab_header_hover,
.tab.filtered>.tab_header_hover {
border:1px solid var(--tab_filtered_hover_border);
background-color:var(--tab_filtered_hover_background);
}
.tab.filtered>.tab_header_hover>.tab_title {
color:var(--tab_filtered_hover_title_font_color);
font-style:var(--tab_filtered_hover_title_font_style);
font-weight:var(--tab_filtered_hover_title_font_weight);
}
/* search result active */
.pin.filtered.active_tab>.tab_header,
.tab.filtered.active_tab>.tab_header {
border:1px solid var(--tab_filtered_active_border);
background-color:var(--tab_filtered_active_background);
}
.tab.filtered.active_tab>.tab_header>.tab_title {
color:var(--tab_filtered_active_title_font_color);
font-style:var(--tab_filtered_active_title_font_style);
font-weight:var(--tab_filtered_active_title_font_weight);
}
/* search result active hover */
.pin.filtered.active_tab>.tab_header_hover,
.tab.filtered.active_tab>.tab_header_hover {
border:1px solid var(--tab_filtered_active_hover_border);
background-color:var(--tab_filtered_active_hover_background);
}
.tab.filtered.active_tab>.tab_header_hover>.tab_title {
color:var(--tab_filtered_active_hover_title_font_color);
font-style:var(--tab_filtered_active_hover_title_font_style);
font-weight:var(--tab_filtered_active_hover_title_font_weight);
}
/* search result selected */
.pin.selected.filtered>.tab_header,
.tab.selected.filtered>.tab_header {
border:1px solid var(--tab_filtered_selected_border);
background-color:var(--tab_filtered_selected_background);
}
.tab.selected.filtered>.tab_header>.tab_title {
color:var(--tab_filtered_selected_title_font_color);
font-style:var(--tab_filtered_selected_title_font_style);
font-weight:var(--tab_filtered_selected_title_font_weight);
}
/* search result selected hover */
.pin.selected.filtered>.tab_header_hover,
.tab.selected.filtered>.tab_header_hover {
border:1px solid var(--tab_filtered_selected_hover_border);
background-color:var(--tab_filtered_selected_hover_background);
}
.tab.selected.filtered>.tab_header_hover>.tab_title {
color:var(--tab_filtered_selected_hover_title_font_color);
font-style:var(--tab_filtered_selected_hover_title_font_style);
font-weight:var(--tab_filtered_selected_hover_title_font_weight);
}
/* search result active selected */
.pin.selected.filtered.active_tab>.tab_header,
.tab.selected.filtered.active_tab>.tab_header {
border:1px solid var(--tab_filtered_selected_active_border);
background-color:var(--tab_filtered_selected_active_background);
}
.tab.selected.filtered.active_tab>.tab_header>.tab_title {
color:var(--tab_filtered_selected_active_title_font_color);
font-style:var(--tab_filtered_selected_active_title_font_style);
font-weight:var(--tab_filtered_selected_active_title_font_weight);
}
/* search result active selected hover */
.pin.selected.filtered.active_tab>.tab_header_hover,
.tab.selected.filtered.active_tab>.tab_header_hover {
border:1px solid var(--tab_filtered_selected_active_hover_border);
background-color:var(--tab_filtered_selected_active_hover_background);
}
.tab.filtered.selected.active_tab>.tab_header_hover>.tab_title {
color:var(--tab_filtered_selected_active_hover_title_font_color);
font-style:var(--tab_filtered_selected_active_hover_title_font_style);
font-weight:var(--tab_filtered_selected_active_hover_title_font_weight);
}
/* search result highlighted */
.pin.filtered.highlighted_search>.tab_header,
.tab.filtered.highlighted_search>.tab_header {
border:1px solid var(--tab_filtered_highlighted_search_border);
background-color:var(--tab_filtered_highlighted_search_background);
}
.tab.filtered.highlighted_search>.tab_header>.tab_title {
color:var(--tab_filtered_highlighted_search_title_font_color);
font-style:var(--tab_filtered_highlighted_search_title_font_style);
font-weight:var(--tab_filtered_highlighted_search_title_font_weight);
}
/* search result highlighted hover */
.pin.filtered.highlighted_search>.tab_header_hover,
.tab.filtered.highlighted_search>.tab_header_hover {
border:1px solid var(--tab_filtered_highlighted_search_hover_border);
background-color:var(--tab_filtered_highlighted_search_hover_background);
}
.tab.filtered.highlighted_search>.tab_header_hover>.tab_title {
color:var(--tab_filtered_highlighted_search_hover_title_font_color);
font-style:var(--tab_filtered_highlighted_search_hover_title_font_style);
font-weight:var(--tab_filtered_highlighted_search_hover_title_font_weight);
}
/* search result active highlighted */
.pin.active_tab.filtered.highlighted_search>.tab_header,
.tab.active_tab.filtered.highlighted_search>.tab_header {
border:1px solid var(--tab_filtered_active_highlighted_search_border);
background-color:var(--tab_filtered_active_highlighted_search_background);
}
.tab.active_tab.filtered.highlighted_search>.tab_header>.tab_title {
color:var(--tab_filtered_active_highlighted_search_title_font_color);
font-style:var(--tab_filtered_active_highlighted_search_title_font_style);
font-weight:var(--tab_filtered_active_highlighted_search_title_font_weight);
}
/* search result active highlighted hover */
.pin.active_tab.filtered.highlighted_search>.tab_header_hover,
.tab.active_tab.filtered.highlighted_search>.tab_header_hover {
border:1px solid var(--tab_filtered_active_highlighted_search_hover_border);
background-color:var(--tab_filtered_active_highlighted_search_hover_background);
}
.tab.active_tab.filtered.highlighted_search>.tab_header_hover>.tab_title {
color:var(--tab_filtered_active_highlighted_search_hover_title_font_color);
font-style:var(--tab_filtered_active_highlighted_search_hover_title_font_style);
font-weight:var(--tab_filtered_active_highlighted_search_hover_title_font_weight);
}
/* search result selected highlighted */
.pin.selected.filtered.highlighted_search>.tab_header,
.tab.selected.filtered.highlighted_search>.tab_header {
border:1px solid var(--tab_filtered_selected_highlighted_search_border);
background-color:var(--tab_filtered_selected_highlighted_search_background);
}
.tab.selected.filtered.highlighted_search>.tab_header>.tab_title {
color:var(--tab_filtered_selected_highlighted_search_title_font_color);
font-style:var(--tab_filtered_selected_highlighted_search_title_font_style);
font-weight:var(--tab_filtered_selected_highlighted_search_title_font_weight);
}
/* search result selected highlighted hover */
.pin.selected.filtered.highlighted_search>.tab_header_hover,
.tab.selected.filtered.highlighted_search>.tab_header_hover {
border:1px solid var(--tab_filtered_selected_highlighted_search_hover_border);
background-color:var(--tab_filtered_selected_highlighted_search_hover_background);
}
.tab.selected.filtered.highlighted_search>.tab_header_hover>.tab_title {
color:var(--tab_filtered_selected_highlighted_search_hover_title_font_color);
font-style:var(--tab_filtered_selected_highlighted_search_hover_title_font_style);
font-weight:var(--tab_filtered_selected_highlighted_search_hover_title_font_weight);
}
/* search result selected active highlighted */
.pin.active_tab.selected.filtered.highlighted_search>.tab_header,
.tab.active_tab.selected.filtered.highlighted_search>.tab_header {
border:1px solid var(--tab_filtered_selected_active_highlighted_search_border);
background-color:var(--tab_filtered_selected_active_highlighted_search_background);
}
.tab.active_tab.selected.filtered.highlighted_search>.tab_header>.tab_title {
color:var(--tab_filtered_selected_active_highlighted_search_title_font_color);
font-style:var(--tab_filtered_selected_active_highlighted_search_title_font_style);
font-weight:var(--tab_filtered_selected_active_highlighted_search_title_font_weight);
}
/* search result selected active highlighted hover */
.pin.active_tab.selected.filtered.highlighted_search>.tab_header_hover,
.tab.active_tab.selected.filtered.highlighted_search>.tab_header_hover {
border:1px solid var(--tab_filtered_selected_active_highlighted_search_hover_border);
background-color:var(--tab_filtered_selected_active_highlighted_search_hover_background);
}
.tab.active_tab.selected.filtered.highlighted_search>.tab_header_hover>.tab_title {
color:var(--tab_filtered_selected_active_highlighted_search_hover_title_font_color);
font-style:var(--tab_filtered_selected_active_highlighted_search_hover_title_font_style);
font-weight:var(--tab_filtered_selected_active_highlighted_search_hover_title_font_weight);
}
.group>.children>.tab:first-child>.drag_indicator,
.group>.children>.folder:first-child>.drag_indicator {
top: 1px;
}
@ -1297,12 +1304,6 @@ div {
/* MEDIA */
@keyframes blinking2 {
0% {opacity: 0}
30% {opacity: 1}
70% {opacity: 1}
100% {opacity: 0}
}
.tab_mediaicon {
animation: none;
position: absolute;
@ -1317,7 +1318,6 @@ div {
}
.audible>.tab_header>.tab_mediaicon {
animation: blinking2 1.5s infinite;
display: inline-block;
height: var(--tab_mediaicon_height);
width: var(--tab_mediaicon_width);
@ -1330,7 +1330,6 @@ div {
}
.muted>.tab_header>.tab_mediaicon {
animation: blinking2 1.5s infinite;
display: inline-block;
height: var(--tab_mediaicon_height);
width: var(--tab_mediaicon_width);
@ -1372,9 +1371,9 @@ div {
width: var(--close_width);
background-color: var(--close_x);
-webkit-mask-image: url(../theme/close.svg);
-webkit-mask-size: var(--close_height) var(--close_width);
-webkit-mask-size: 100% 100%;
mask-image: url(../theme/close.svg);
mask-size: 100%;
mask-size: var(--close_width) var(--close_height);
mask-position: center, center;
}
@ -1403,16 +1402,12 @@ div {
border: none;
}
.folder_header.folder_header_hover,
.tab_header.tab_header_hover {
z-index: 9999;
}
.dragged_tree>.folder_header,
.dragged_tree>.tab_header {
.folder.dragged_tree>.folder_header,
.pin.dragged_tree>.tab_header,
.tab.dragged_tree>.tab_header {
border: 1px solid var(--tab_selected_border);
background-color: var(--tab_selected_background);
}
@ -1432,7 +1427,8 @@ div {
.o>.tab_header>.tab_counter,
.c>.folder_header>.folder_counter,
.c>.tab_header>.tab_counter {
opacity: 0.3;
font-family: Arial, Helvetica, "Nimbus Sans L", "Liberation Sans", FreeSans, Sans-serif;
opacity: 0.7;
display: block;
position: absolute;
vertical-align: bottom;
@ -1441,42 +1437,45 @@ div {
top: var(--counter_top);
text-overflow: ellipsis;
width: auto;
height: var(--counter_height);
height: var(--counter_size);
padding-top: 0px;
padding-bottom: 0px;
padding-left: 1px;
padding-right: 1px;
overflow: hidden;
border: 1px solid #e7e7e7;
border-radius: 6px;
background-color: #e7e7e7;
line-height: 10px;
}
.o>.folder_header:hover>.folder_counter,
.o>.tab_header:hover>.tab_counter,
.c>.folder_header:hover>.folder_counter,
.c>.tab_header:hover>.tab_counter {
opacity: 0.9;
height: calc(var(--counter_height) + 1px);
opacity: 1;
}
/*
.o>.tab_header:hover>.tab_counter>.counter_number,
.c>.tab_header:hover>.tab_counter>.counter_number,
.o>.folder_header:hover>.folder_counter>.counter_number,
.c>.folder_header:hover>.folder_counter>.counter_number {
top: calc(var(--counter_number_top) + 1px);
font-size: calc(var(--counter_font_size) + 1px);
}
line-height: calc(var(--counter_height) + 4px);
}
*/
.folder_counter>.counter_number,
.tab_counter>.counter_number {
position: relative;
top: var(--counter_number_top);
font-family: Arial, Helvetica, "Nimbus Sans L", "Liberation Sans", FreeSans, Sans-serif;
white-space: nowrap;
font-size: var(--counter_font_size);
/* color: #303030; */
font-size: var(--counter_size);
color: #000000;
padding-left: 1px;
padding-right: 1px;
line-height: 1px;
bottom: var(--counter_number);
}

View File

@ -0,0 +1,9 @@
@keyframes attention_blinking {
0% {background-color: var(--tab_background); border:1px solid var(--tab_border);}
50% {background-color: var(--attention_background); border:1px solid var(--attention_border);}
80% {background-color: var(--tab_background); border:1px solid var(--tab_border);}
100% {background-color: var(--tab_background); border:1px solid var(--tab_border);}
}
.pin.attention>.tab_header {
animation: attention_blinking 2.5s infinite;
}

View File

@ -0,0 +1,12 @@
@keyframes audio_blinking {
0% {opacity: 0}
30% {opacity: 1}
70% {opacity: 1}
100% {opacity: 0}
}
.audible>.tab_header>.tab_mediaicon {
animation: audio_blinking 1.5s infinite;
}
.muted>.tab_header>.tab_mediaicon {
animation: audio_blinking 1.5s infinite;
}

View File

@ -7,9 +7,7 @@ body {
--pin_height: 22px;
--tab_height: 16px;
--tab_height_line: 16px;
--title_font_size: 10.5px;
--title_font_size: 11px;
--tab_title_text_padding_left: 18px;
--tab_title_text_padding_exp_left: 25px;
@ -29,16 +27,15 @@ body {
--children_padding_left: 5px;
--close_top: 1px;
--close_right: 0px;
--close_right: 1px;
--close_height: 12px;
--close_width: 12px;
--tab_mediaicon_height: 8px;
--tab_mediaicon_width: 8px;
--counter_height: 5px;
--counter_left: 19px;
--counter_size: 7px;
--counter_top: 0px;
--counter_font_size: 7px;
--counter_number_top: -3px;
--counter_left: 18px;
--counter_number: -3px;
}

View File

@ -6,10 +6,8 @@ body {
--pin_width: 22px;
--pin_height: 22px;
--tab_height: 17px;
--tab_height_line: 18px;
--title_font_size: 10.5px;
--tab_height: 18px;
--title_font_size: 12px;
--tab_title_text_padding_left: 21px;
--tab_title_text_padding_exp_left: 30px;
@ -30,15 +28,14 @@ body {
--children_padding_left: 5px;
--close_top: 1px;
--close_right: 1px;
--close_height: 13px;
--close_height: 14px;
--close_width: 13px;
--tab_mediaicon_height: 9px;
--tab_mediaicon_width: 9px;
--counter_height: 6px;
--counter_left: 21px;
--counter_size: 7px;
--counter_top: 0px;
--counter_font_size: 8px;
--counter_number_top: -2px;
--counter_left: 21px;
--counter_number: -3px;
}

View File

@ -7,9 +7,7 @@ body {
--pin_height: 24px;
--tab_height: 20px;
--tab_height_line: 23px;
--title_font_size: 12px;
--title_font_size: 14px;
--tab_title_text_padding_left: 26px;
--tab_title_text_padding_exp_left: 35px;
@ -29,17 +27,15 @@ body {
--children_padding_left: 5px;
--close_top: 2px;
--close_right: 1px;
--close_right: 2px;
--close_height: 14px;
--close_width: 14px;
--tab_mediaicon_height: 10px;
--tab_mediaicon_width: 10px;
--counter_height: 6px;
--counter_left: 24px;
/* --counter_left: 1px; */
--counter_size: 8px;
--counter_top: 1px;
--counter_font_size: 8px;
--counter_number_top: -2px;
--counter_left: 24px;
--counter_number: -4px;
}

View File

@ -7,9 +7,7 @@ body {
--pin_height: 26px;
--tab_height: 22px;
--tab_height_line: 24px;
--title_font_size: 13px;
--title_font_size: 14px;
--tab_title_text_padding_left: 25px;
--tab_title_text_padding_exp_left: 37px;
@ -36,9 +34,8 @@ body {
--tab_mediaicon_height: 11px;
--tab_mediaicon_width: 11px;
--counter_height: 6px;
--counter_left: 26px;
--counter_size: 8px;
--counter_top: 1px;
--counter_font_size: 8px;
--counter_number_top: -2px;
--counter_left: 26px;
--counter_number: -4px;
}

View File

@ -7,16 +7,14 @@ body {
--pin_height: 28px;
--tab_height: 24px;
--tab_height_line: 26px;
--title_font_size: 14px;
--title_font_size: 15px;
--tab_title_text_padding_left: 27px;
--tab_title_text_padding_exp_left: 39px;
--tab_title_text_padding_right_with_close_button: 24px;
--favicon_width: 18px;
--favicon_height: 18px;
--favicon_width: 16px;
--favicon_height: 16px;
--favicon_left: 3px;
--expand_height: 23px;
@ -36,9 +34,8 @@ body {
--tab_mediaicon_height: 12px;
--tab_mediaicon_width: 12px;
--counter_height: 6px;
--counter_left: 28px;
--counter_size: 8px;
--counter_top: 1px;
--counter_font_size: 8px;
--counter_number_top: -2px;
--counter_left: 28px;
--counter_number: -4px;
}

View File

@ -0,0 +1,41 @@
body {
--scrollbar_height: 4px;
--scrollbar_width: 16px;
--pin_width: 30px;
--pin_height: 30px;
--tab_height: 26px;
--title_font_size: 16px;
--tab_title_text_padding_left: 29px;
--tab_title_text_padding_exp_left: 41px;
--tab_title_text_padding_right_with_close_button: 24px;
--favicon_width: 16px;
--favicon_height: 16px;
--favicon_left: 3px;
--expand_height: 25px;
--expand_width: 45px;
--expand_mask_top: 10px;
--expand_mask_left: 29px;
--expand_mask_height: 7px;
--expand_mask_width: 7px;
--children_padding_left: 5px;
--close_top: 5px;
--close_right: 5px;
--close_height: 14px;
--close_width: 14px;
--tab_mediaicon_height: 13px;
--tab_mediaicon_width: 13px;
--counter_size: 8px;
--counter_top: 1px;
--counter_left: 30px;
--counter_number: -4px;
}

View File

@ -23,6 +23,5 @@ body {
--pin_list_padding_bottom: 2px;
--pin_list_padding_left: 2px;
--group_folders_top: 2px;
--group_tabs_top: 2px;
}

View File

@ -23,6 +23,5 @@ body {
--pin_list_padding_bottom: 1px;
--pin_list_padding_left: 1px;
--group_folders_top: 1px;
--group_tabs_top: 1px;
}

View File

@ -23,6 +23,5 @@ body {
--pin_list_padding_bottom: 0px;
--pin_list_padding_left: 0px;
--group_folders_top: -1px;
--group_tabs_top: -1px;
--group_tabs_top: 0px;
}

View File

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Tree Tabs - translation tool</title>
</head>
<body id="body" class="sidebar_body">
<button type="button" id="load_translation" style="position: relative; margin:10px;">Load translated file</button>
<button type="button" id="export_translation" style="position: relative; margin:10px;">Export translation</button>
<a href="mailto:karol@jagiello.it">Send your translation here</a>
<script type="text/javascript" src="./translator.js"></script>
</body>
</html>

121
translator/translator.js Normal file
View File

@ -0,0 +1,121 @@
const english_base = {"extensionName":{"message":"Tree Tabs"},"extDesc":{"message":"Manage your tabs in the sidebar!"},"OpenSidebar":{"message":"Open Tree Tabs"},"button_new":{"message":"Press left mouse button to open new tab. \nPress middle mouse button to clone the active tab. \nPress right mouse button to scroll the list to the active tab."},"button_pin":{"message":"Pin / Unpin current tab"},"button_undo":{"message":"Reopen last closed"},"button_reboot":{"message":"Reload Tree Tabs_ Try this in case your tree hierarchy is lost after restart."},"button_detach":{"message":"Detach tab"},"button_move":{"message":"Detach tab"},"button_search":{"message":"Search tabs"},"button_tools":{"message":"Tools"},"button_groups":{"message":"Groups"},"filter_search_go_prev":{"message":"Previous search result"},"filter_search_go_next":{"message":"Next search result"},"button_bookmarks":{"message":"Unsorted bookmarks"},"button_downloads":{"message":"Downloads"},"button_history":{"message":"History"},"button_settings":{"message":"Settings"},"button_options":{"message":"Tree Tabs settings"},"button_extensions":{"message":"Extensions"},
"button_unload":{"message":"Unload tabs"},"button_discard":{"message":"Unload tabs"},"button_filter_type":{"message":"Search titles or urls"},"button_groups_toolbar_hide":{"message":"Hide/Show Groups toolbar"},"button_new_group":{"message":"New group"},"button_remove_group":{"message":"Remove group.\nHold shift key to close tabs from this group"},"button_edit_group":{"message":"Rename group"},"button_import_group":{"message":"Import group"},"button_export_group":{"message":"Export group"},"button_backup":{"message":"Session"},"button_import_bak":{"message":"Import session"},"button_import_merge_bak":{"message":"Import and merge session.\nImporter will try to match current tabs with those from saved session, instead of opening a new window."},"button_export_bak":{"message":"Export session"},"button_load_bak1":{"message":"EMERGENCY if lost groupings: Load latest internal backup (autosave is made every 5 minutes)"},"button_load_bak2":{"message":"EMERGENCY if lost groupings: Load previous to latest internal backup (autosave is made every 10 minutes)"},
"button_load_bak3":{"message":"EMERGENCY if lost groupings: Load oldest internal backup (autosave is made every 30 minutes)"},"button_folders":{"message":"Folders"},"button_new_folder":{"message":"New folder"},"button_remove_folder":{"message":"Remove selected folder/s"},"button_edit_folder":{"message":"Rename folder"},"menu_expand_all":{"message":"Expand all trees"},"menu_collapse_all":{"message":"Collapse all trees"},"menu_expand_tree":{"message":"Expand tree"},"menu_collapse_tree":{"message":"Collapse tree"},"menu_new_tab":{"message":"New tab"},"menu_new_pin":{"message":"New pinned tab"},"menu_duplicate_tab":{"message":"Duplicate"},"menu_detach_tab":{"message":"Detach"},"menu_reload_tab":{"message":"Reload"},"menu_pin_tab":{"message":"Pin"},"menu_mute_tab":{"message":"Mute"},"menu_mute_tree":{"message":"Mute tree"},"menu_unmute_tree":{"message":"Unmute tree"},"menu_unmute_tab":{"message":"Unmute"},"menu_mute_other":{"message":"Mute other"},"menu_unmute_other":{"message":"Unmute other"},"menu_unpin_tab":{"message":"Unpin"},"menu_close_tree":{"message":"Close tree"},"menu_close":{"message":"Close"},
"menu_close_other":{"message":"Close other"},"menu_undo_close_tab":{"message":"Undo close"},"menu_treetabs_settings":{"message":"Settings"},"menu_unload":{"message":"Unload"},"menu_bookmark_tree":{"message":"Bookmark"},"menu_new_folder":{"message":"New folder"},"menu_rename_folder":{"message":"Rename folder"},"menu_delete_folder":{"message":"Delete"},"menu_new_group":{"message":"New group"},"menu_rename_group":{"message":"Rename"},"menu_delete_group":{"message":"Delete"},"menu_delete_group_tabs_close":{"message":"Delete with tabs"},"menu_groups_unload":{"message":"Unload"},"menu_bookmark_group":{"message":"Bookmark"},"menu_groups_hibernate":{"message":"Hibernate"},"menu_group_tabs_close":{"message":"Close tabs"},"status_bar_rearranging_tabs":{"message":"Rearranging tabs and folders"},"status_bar_rearranging_finished":{"message":"Rearranging: done."},"status_bar_loaded_tree_structure":{"message":"Loaded Tree structure..."},"status_bar_finding_ref_tabs":{"message":"Finding reference tabs..."},"status_bar_finding_other_windows":{"message":"Finding other windows to add tabs..."},
"status_bar_all_done":{"message":"All done."},"status_bar_autosave":{"message":"Autosave: "},"status_bar_quick_check_recreate_structure":{"message":"Quick check and recreating structure..."},"options_vivaldi":{"message":" Vivaldi "},"opt_url_for_web_panel":{"message":"Url for the Web Panel"},"options_pinned":{"message":" Pinned tabs bar "},"options_pin_list_multi_row":{"message":"Multi row list"},"option_allow_pin_close":{"message":"Allow to close pinned tabs"},"option_pin_attention_blinking":{"message":"Blink pinned tabs that ask for attention"},"option_audio_blinking":{"message":"Blink audio indicator"},"options_tabs":{"message":" Tabs "},"options_syncro_tabbar_tabs_order":{"message":"Synchronize browser tabs order with Tree Tabs, tabs can be unresponsive for a second after drag&drop. This option is needed for correct ctrl+tab switching. You can disable this option if you don't use keyboard shortcuts."},"options_switch_with_scroll":{"message":"Switch tabs with mouse wheel"},"options_tab_group_regex":{"message":"Tab group assignments (Items matching the given pattern will be moved to the designated group. Pattern accepts regular expressions.)"},
"option_tab_match":{"message":"Pattern"},"option_tab_group":{"message":"Group"},"options_orphaned_tabs_to_ungrouped":{"message":"Always place orphan tabs in the 'ungrouped' group"},"options_move_on_url_change":{"message":"Move tabs that match regexes"},"options_move_on_url_change_never":{"message":"never"},"options_move_on_url_change_from_empty":{"message":"when URL changes in Home tab (only Home tabs created by ctrl+t shortcut)"},"options_move_on_url_change_from_empty_b":{"message":"when URL changes in any Home tab"},"options_move_on_url_change_all_new":{"message":"when tab is created with a matching URL"},"options_move_on_url_change_always":{"message":"whenever URL changes to a matching pattern"},"options_always_show_close":{"message":"Show close button on all tabs and folders"},"options_never_show_close":{"message":"Never show close button (option above will be ignored)"},"options_collapse_other_trees":{"message":"Automatically collapse other trees on expand"},"options_open_tree_on_hover":{"message":"Auto expand collapsed trees when dragging and holding for a second over them"},
"options_promote_children":{"message":"Promote children on close, if disabled, when closing the parent of a tree structure, all tabs and folders will be closed (be careful, because undo close tab will not recover the trees structure)"},"options_promote_children_in_first_child":{"message":"Promote first child as a parent"},"options_skip_load":{"message":"Discard tree structure after browser's restart, this option is for those who don't use browser's session. Basically it disables loading database at startup."},"options_midclick_tab":{"message":"Action for middle mouse click on tab"},"options_dbclick_tab":{"message":"Action for double click on tab"},"options_action_tab_none":{"message":"nothing"},"options_action_tab_new":{"message":"open new tab"},"options_action_tab_expand_collapse":{"message":"expand/collapse tree"},"options_action_tab_close":{"message":"close tab"},"options_action_tab_reload":{"message":"reload tab"},"options_action_tab_unload":{"message":"unload tab"},"options_action_tab_activate_previous_active":{"message":"go back to previous active tab (works only on unpinned tabs)"},
"options_action_tab_undo_close":{"message":"reopen last closed tab"},"options_midclick_group":{"message":"Action for middle click on empty space on the left side or below the tabs"},"options_dbclick_group":{"message":"Action for double click on empty space on the left side or below the tabs"},"options_action_group_none":{"message":"nothing"},"options_action_group_new":{"message":"open new tab"},"options_action_group_activate_previous_active":{"message":"go back to previous active tab (works only on unpinned tabs)"},"options_action_group_undo_close_tab":{"message":"reopen last closed tab"},"options_append_pinned_tab":{"message":"Place pinned tabs"},"options_append_pinned_tab_first":{"message":"as first"},"options_append_pinned_tab_after":{"message":"after opener, or active"},"options_append_pinned_tab_last":{"message":"as last"},"options_append_child_tab":{"message":"Place children tabs"},"options_append_child_tab_top":{"message":"at the top (reverse hierarchy)"},"options_append_child_tab_bottom":{"message":" at the bottom"},"options_append_child_tab_after":{"message":"after parent tab (no automatic tree)"},
"options_append_orphan_tab":{"message":"Append orphan tabs"},"options_append_orphan_tab_top":{"message":"at the top of the group"},"options_append_orphan_tab_after_active":{"message":"after active tab"},"options_append_orphan_tab_bottom":{"message":"at the bottom of the group"},"options_append_orphan_tab_as_child":{"message":"treat as active's tab child"},"options_append_orphan_tab_active_parent_top":{"message":"at the same level as active tab, but on top"},"options_append_orphan_tab_active_parent_bottom":{"message":"at the same level as active tab, but on bottom"},"options_toolbar_new_tab":{"message":"Toolbar + (new tab button) should append tab"},"options_toolbar_new_tab_as_regular_orphan":{"message":"as a regular orphan tab (option above)"},"options_toolbar_new_tab_root_of_group":{"message":"at the bottom of the group"},"options_after_closing_active_tab":{"message":"After closing active tab,"},"options_after_closing_active_tab_go_up":{"message":"activate tab above"},"options_after_closing_active_tab_go_down":{"message":"activate tab below"},"options_after_closing_active_tab_go_up_seek_in_parent":{"message":"activate tab above if on the same level"},
"options_after_closing_active_tab_go_down_seek_in_parent":{"message":"activate tab below if on the same level"},"options_after_closing_active_tab_go_browser":{"message":"let browser activate tab"},"options_append_child_tab_after_limit":{"message":"Once reached maximum tree depth, place tab on the same level, but"},"options_append_child_tab_after_limit_top":{"message":"at the top"},"options_append_child_tab_after_limit_after":{"message":"after parent"},"options_append_child_tab_after_limit_bottom":{"message":"at the bottom"},"options_show_counter_tabs":{"message":"Show children tabs count on tabs and folders titles"},"options_show_counter_tabs_hints":{"message":"Show children tabs count in tabs and folders hints"},"options_max_tree_depth":{"message":"Maximum tree depth: set it to -1 for unlimited branches, 0 for flat tabs placement (no trees), any number above 0 will be its maximum"},"options_max_tree_drag_drop":{"message":"Limit Drag&Drop to tree's maximum depth, so you can't drop tabs beyond maximum depth"},"options_groups":{"message":"Groups"},"options_show_counter_groups":{"message":"Show tabs count on groups"},
"options_groups_toolbar_default":{"message":"Show groups toolbar in new windows"},"options_syncro_tabbar_groups_tabs_order":{"message":"Synchronize browser tabs order after drag&drop of the group tabs. Tabs will sort for a long time, if browser has a lot of tabs open. This option is needed for correct ctrl+tab switching. You can disable this option if you don't use keyboard shortcuts."},"options_hide_other_groups_tabs_firefox":{"message":"Show Firefox tabs from current group only. Requires change in about:config, find 'extensions.webextensions.tabhide.enabled' and set it to true."},"options_folders":{"message":"Folders"},"options_midclick_folder":{"message":"Action for middle mouse click on folder"},"options_dbclick_folder":{"message":"Action for double click on folder"},"options_action_folder_none":{"message":"nothing"},"options_action_folder_rename":{"message":"rename folder"},"options_action_folder_new_folder":{"message":"open new folder"},"options_action_folder_new_tab":{"message":"open new tab"},"options_action_folder_expand_collapse":{"message":"expand/collapse tree"},"options_action_folder_close":{"message":"close folder"},
"options_action_folder_unload":{"message":"unload tabs in folder"},"options_global":{"message":"Global"},"options_theme":{"message":"Theme"},"options_rename_theme_button":{"message":"Rename"},"options_add_theme_button":{"message":"Add new"},"options_remove_theme_button":{"message":"Remove"},"options_import_theme_button":{"message":"Import"},"options_export_theme_button":{"message":"Export"},"options_share_theme_link":{"message":"Get more!"},"options_toolbar":{"message":" Toolbar "},"options_available_buttons":{"message":"Drag and drop buttons to arrange them, drop to the green box, buttons you don't want to use"},"options_reset_toolbar_button":{"message":"Reset toolbar"},"options_export_debug":{"message":"Export log file"},"options_print_debug":{"message":"Load log from file"},"options_toolbar_look":{"message":" Toolbar's look "},"hint_orphan_tab":{"message":"Orphan tab is a tab opened from an external source, which can be:"},"hint_ctrl_t":{"message":"ctrl+t shortcut"},"hint_from_pin":{"message":"link that opens new tab from pinned tab"},"hint_from_bookmark":{"message":"bookmark"},"hint_from_external_link":{"message":"external link"},
"hint_from_popup":{"message":"popup opened as a tab (settings in browser, popup blocker or anything that redirects popups to new tabs)"},"hint_explained_new_tab_settings":{"message":"+ button in Tree Tabs toolbar, places new tabs in the root of the active group, unless set differently."},"hint_explained_orphan_after_active_settings":{"message":"If set to 'after active tab' and active tab is not in current group, tab will append to the root of the active group instead."},"button_background":{"message":"Toolbar buttons background"},"button_hover_background":{"message":"Toolbar buttons background, on mouse hover"},"button_on_background":{"message":"Toolbar active buttons background"},"button_icons":{"message":"Toolbar buttons icon color"},"button_icons_hover":{"message":"Toolbar buttons icon color, on mouse hover"},"button_on_icons":{"message":"Toolbar active buttons icon color"},"button_border":{"message":"Toolbar buttons border color"},"button_hover_border":{"message":"Toolbar buttons border color, on mouse hover"},"filter_box_font":{"message":"Search box, font color"},"filter_box_background":{"message":"Search box, font background color"},
"filter_box_border":{"message":"Search box, border color"},"filter_clear_icon":{"message":"Clear search result x button color"},"toolbar_background":{"message":"Toolbar background color"},"toolbar_shelf_background":{"message":"Toolbar's shelf background color"},"toolbar_border_bottom":{"message":"Toolbar borders color"},"button_shelf_background":{"message":"Toolbar's shelf buttons background color"},"button_shelf_hover_background":{"message":"Toolbar's shelf buttons background color, on mouse hover"},"button_shelf_icons":{"message":"Toolbar's shelf buttons icon color"},"button_shelf_icons_hover":{"message":"Toolbar's shelf buttons icon color, on mouse hover"},"button_shelf_border":{"message":"Toolbar's shelf buttons border color"},"button_shelf_hover_border":{"message":"Toolbar's shelf buttons border color, on mouse hover"},"options_theme_tabs":{"message":" Tabs look "},"options_tabs_margin_overlap":{"message":"Tabs spacing:\nOverlap 1px, best for themes with borders"},"options_tabs_margin_0":{"message":"Tabs spacing:\nNo spacing, best for flat look"},"options_tabs_margin_1":{"message":"Tabs spacing:\nDefault, 1px between tabs"},
"options_tab_list_scrollbar_width_down":{"message":"Decrease scrollbars width"},"options_tab_list_scrollbar_width_up":{"message":"Increase scrollbars width"},"options_tab_list_scrollbar_height_down":{"message":"Decrease scrollbars height"},"options_tab_list_scrollbar_height_up":{"message":"Increase scrollbars height"},"options_tabs_indentation_down":{"message":"Decrease tabs indentation"},"options_tabs_indentation_up":{"message":"Increase tabs indentation"},"options_tabs_roundness_down":{"message":"Make tabs corners more square"},"options_tabs_roundness_up":{"message":"Make tabs rounder"},"options_tabs_size_down":{"message":"Decrease tabs size"},"options_tabs_size_up":{"message":"Increase tabs size"},"options_theme_tabs_sample_text_normal":{"message":"Normal"},"options_theme_tabs_sample_text_normal_hover":{"message":"Normal, mouse hover over"},"options_theme_tabs_sample_text_normal_selected":{"message":"Normal selected"},"options_theme_tabs_sample_text_normal_selected_hover":{"message":"Normal selected, mouse hover over"},"options_theme_tabs_sample_text_active":{"message":"Active"},"options_theme_tabs_sample_text_active_hover":{"message":"Active, mouse hover over"},
"options_theme_tabs_sample_text_active_selected":{"message":"Active and selected"},"options_theme_tabs_sample_text_active_selected_hover":{"message":"Active and selected, mouse hover over"},"options_theme_tabs_sample_text_discarded":{"message":"Unloaded (discarded)"},"options_theme_tabs_sample_text_discarded_hover":{"message":"Unloaded, mouse hover over"},"options_theme_tabs_sample_text_discarded_selected":{"message":"Unloaded and selected"},"options_theme_tabs_sample_text_discarded_selected_hover":{"message":"Unloaded and selected, mouse hover over"},"options_theme_tabs_sample_text_search_result":{"message":"Search result"},"options_theme_tabs_sample_text_search_result_hover":{"message":"Search result, mouse hover over"},"options_theme_tabs_sample_text_search_result_active":{"message":"Search result active"},"options_theme_tabs_sample_text_search_result_active_hover":{"message":"Search result active, mouse hover over"},"options_theme_tabs_sample_text_search_result_selected":{"message":"Search result selected"},"options_theme_tabs_sample_text_search_result_selected_hover":{"message":"Search result selected, mouse hover over"},
"options_theme_tabs_sample_text_search_result_selected_active":{"message":"Search result selected, active"},"options_theme_tabs_sample_text_search_result_selected_active_hover":{"message":"Search result selected, active, mouse hover over"},"options_theme_tabs_sample_text_search_result_highlighted":{"message":"Search result highlighted"},"options_theme_tabs_sample_text_search_result_highlighted_hover":{"message":"Search result highlighted, mouse hover over"},"options_theme_tabs_sample_text_search_result_highlighted_active":{"message":"Search result highlighted, active"},"options_theme_tabs_sample_text_search_result_highlighted_active_hover":{"message":"Search result highlighted, active, mouse hover over"},"options_theme_tabs_sample_text_search_result_highlighted_selected":{"message":"Search result highlighted, selected"},"options_theme_tabs_sample_text_search_result_highlighted_selected_hover":{"message":"Search result highlighted, selected, mouse hover over"},"options_theme_tabs_sample_text_search_result_highlighted_selected_active":{"message":"Search result highlighted, selected, active"},
"options_theme_tabs_sample_text_search_result_highlighted_selected_active_hover":{"message":"Search result highlighted, selected, active, mouse hover over"},"attention_background":{"message":"Tabs blinking for attention, background color"},"attention_border":{"message":"Tabs blinking for attention, border color"},"pin_list_border_bottom":{"message":"Pinned tabs list, border at the bottom color"},"pin_list_background":{"message":"Pinned tabs list, background color"},"folder_icon_open":{"message":"Open folder icon"},"folder_icon_closed":{"message":"Empty or closed folder icon"},"folder_icon_hover":{"message":"Folder icon on mouse hover"},"expand_open_background":{"message":"Open tree indicator"},"expand_closed_background":{"message":"Closed tree indicator"},"expand_hover_background":{"message":"Tree indicator on mouse hover"},"group_list_button_hover_background":{"message":"Group on mouse hover"},"group_list_borders":{"message":"Group list border"},"group_list_default_font_color":{"message":"Group list default font color"},"group_list_background":{"message":"Group list background color"},"tab_list_background":{"message":"Tabs background color"},
"drag_indicator":{"message":"Drag&Drop indicator"},"close_x":{"message":"x inside the close button"},"close_hover_x":{"message":"x inside the close button, on mouse hover"},"close_hover_border":{"message":"close button border, on mouse hover"},"close_hover_background":{"message":"close button box color, on mouse hover"},"scrollbar_thumb":{"message":"Scrollbar thumb"},"scrollbar_thumb_hover":{"message":"Scrollbar thumb, on mouse hover"},"scrollbar_track":{"message":"Scrollbar track"},"options_example_menu_item":{"message":"menu item"},"options_menu":{"message":" Menu "},"tabs_menu_hover_border":{"message":"menu item border, on mouse hover"},"tabs_menu_hover_background":{"message":"menu item background, on mouse hover"},"tabs_menu_separator":{"message":"menu separator"},"tabs_menu_font":{"message":"menu text color"},"tabs_menu_border":{"message":"menu border"},"tabs_menu_background":{"message":"menu background"},"options_there_is_a_theme_with_this_name":{"message":"Theme with this name already exists, try a new name"},"options_theme_name_cannot_be_empty":{"message":"Theme name cannot be empty, enter some name"},
"options_no_theme_to_export":{"message":"No theme to export, maybe add a new one :)"},"options_loaded_theme_older_version":{"message":"Looks like loaded theme was saved in older version of the extension, some colors or options might be missing"},"options_loaded_theme_newer_version":{"message":"Looks like loaded theme was saved in a newer version of the extension, can't load!"},"options_vivaldi_copied_url":{"message":"Web Panel Url has been copied to clipboard, add a new Web Panel and paste url."},"options_copied_wallet_address":{"message":"Wallet address has been copied to clipboard"},"options_clear_data":{"message":"Sidebar is not loading? Reset! ATTENTION! All options and saved Themes will be lost!"},"options_development":{"message":"Development"},"options_debug":{"message":"Debug"},"group_edit_button_cancel":{"message":"Cancel"},"group_edit_button_confirm":{"message":"Ok"},"folder_edit_button_cancel":{"message":"Cancel"},"folder_edit_button_confirm":{"message":"Ok"},"manager_window_button_label_import_group":{"message":"Import group"},"manager_window_button_label_import_session":{"message":"Import session"},
"manager_window_button_label_save_current_session":{"message":"Save current session"},"caption_ungrouped_group":{"message":"Ungrouped"},"caption_noname_group":{"message":"untitled"},"caption_clear_filter":{"message":"Clear search results"},"caption_loading":{"message":"Loading..."},"caption_searchbox":{"message":" Search tabs..."},"manager_window_header_title":{"message":"Manager"},"menu_manager_window":{"message":"Open manager"},"button_manager_window":{"message":"Open manager window"},"manager_window_groups_button":{"message":"Hibernated groups"},"manager_window_sessions_button":{"message":"Saved sessions"},"manager_window_autosave_button":{"message":"Auto saved sessions"},"manager_window_button_label_hibernate_group":{"message":"Hibernate current group"},"manager_window_autosessions_maximum_saves_label":{"message":"Number of autosaves to keep:"},"manager_window_autosessions_save_timer_label":{"message":"Autosave every (minutes):"},"manager_window_delete_icon":{"message":"Remove"},"manager_window_savetofile_icon":{"message":"Save to file"},"manager_window_merge_icon":{"message":"Load and merge"},"manager_window_load_icon":{"message":"Load"},
"options_Remove_button":{"message":"Remove"},"add_tab_group_regex":{"message":"Add"},"menu_unload_tree":{"message":"Unload tree"}};
let translator = {
Nodes: {
},
init: function() {
for (var Id in english_base) {
translator.Nodes[Id] = new translator.textBox({id: Id, message: english_base[Id].message});
}
document.getElementById("load_translation").onclick = function(event) {
if (event.which == 1) {
translator.File_OpenFile();
}
}
document.getElementById("export_translation").onclick = function(event) {
if (event.which == 1) {
translator.File_SaveFile();
}
}
},
textBox: class {
constructor(p) {
let OriginalText = document.createElement("div");
OriginalText.classList = "original";
OriginalText.id = p.id;
OriginalText.innerHTML = p.message;
body.appendChild(OriginalText);
this.OriginalText = OriginalText;
let TextBox = document.createElement("textarea");
TextBox.classList = "translated";
TextBox.id = p.id;
TextBox.style.width = "100%";
TextBox.value = "";
TextBox.style.whiteSpace = "normal";
TextBox.style.marginBottom = "10px";
body.appendChild(TextBox);
this.TextBox = TextBox;
}
},
File: {
OpenFile: function(extension) {
let body = document.getElementById("body");
let inp = document.createElement("input");
inp.id = "file_import";
inp.type = "file";
inp.accept = extension;
inp.style.display = "none";
body.appendChild(inp);
inp.click();
inp.onchange = function(event) {
let fr = new FileReader();
if (inp.files[0] == undefined) return;
fr.readAsText(inp.files[0]);
fr.onload = function() {
let data = JSON.parse(fr.result);
inp.parentNode.removeChild(inp);
for (var Id in data) {
if (translator.Nodes[Id]) {
translator.Nodes[Id].TextBox.value = data[Id].message;
}
}
}
}
},
SaveFile: function() {
let data = {};
for (var Id in translator.Nodes) {
data[Id] = {"message": translator.Nodes[Id].TextBox.value};
}
let file = new File([JSON.stringify(data)], "messages.json", {type: "text/json;charset=utf-8"});
let body = document.getElementById("body");
let savelink = document.createElement("a");
savelink.href = URL.createObjectURL(file);
savelink.fileSize = file.size;
savelink.target = "_blank";
savelink.style.display = "none";
savelink.type = "file";
savelink.download = "messages.json";
body.appendChild(savelink);
setTimeout(function() {
savelink.click();
setTimeout(function() {
savelink.parentNode.removeChild(savelink);
}, 60000);
}, 10);
}
},
}
translator.init();

14
vivaldi/save_file.html Normal file
View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body id="body">
<p>This tab can be closed after saving file</p>
<script type="text/javascript" src="./save_file.js"></script>
</body>
</html>

24
vivaldi/save_file.js Normal file
View File

@ -0,0 +1,24 @@
function DOM_New(type, parent, parameters, style) {
let NewElement = document.createElement(type);
for (param in parameters) {
NewElement[param] = parameters[param];
}
for (param in style) {
NewElement.style[param] = style[param];
}
if (parent) parent.appendChild(NewElement);
return NewElement;
}
function File_SaveFile(filename, extension, data) {
let file = new File([JSON.stringify(data)], filename + "." + extension, {type: "text/" + extension + ";charset=utf-8"});
let savelink = DOM_New("a", document.getElementById("body"), {href:URL.createObjectURL(file), fileSize: file.size, target: "_blank", type: "file", download: (filename + "." + extension)}, {display: "none"});
savelink.click();
}
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if (message.command == "save_file") {
File_SaveFile(message.filename, message.extension, message.data);
}
});