/
qc-tab-close.js
162 lines (144 loc) · 5.85 KB
/
qc-tab-close.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
(function SetCloseTabButtonQC() {
"use strict";
var lang;
const l10n = {
'en-US': {
tab: 'Tabs'
},
'en-UK': {
tab: 'Tabs'
},
'ja': {
tab: 'タブ'
},
'ja-KS': {
tab: 'タブ'
},
};
vivaldi.utilities.getLanguage().then(l => {
lang = l10n[`${l}`];
});
// Set shortcut close tab
// it can't register specific key what had default function for some reason( ex) Ctrl|Shift|Alt+Backspace).
// It can't register Shift+Delete for some reason(Ctrl|Alt+Delete has default function).
const DELETE_TAB_KEY_COMBO = "Alt+Delete";
function handleKeyboardShortcut(_, combo) {
if(DELETE_TAB_KEY_COMBO !== combo) return;
// Delete tab
const selected = document.querySelector('.quick-command[data-selected]');
const selectedTitle = selected.querySelector('.quick-command-title');
var tabTitle = selectedTitle.textContent.trim();
const isRemoved = removeTabFromTabTitle(tabTitle);
// Delete tab in qc
if(isRemoved) return;
selected.classList.add('strikethrough-text')
}
vivaldi.tabsPrivate.onKeyboardShortcut.addListener(handleKeyboardShortcut);
// Set close button
function addCloseButtonsToQuickCommands() {
// Parent of quick-command-sectionheader and quick-command class
const qcContainer = document.querySelector('.quick-commands');
// Extract qc-commands from React auto generate container tag
const qcCommands = qcContainer.firstChild.firstChild;
for (const command of qcCommands.childNodes) {
// Set button when'quick-command-sectionheader' include 'Tab'
if (command.classList.contains('quick-command-sectionheader')) {
if (command.textContent.includes(lang.tab)) {
continue;
}
else {
// Return when next section-header
return;
}
}
// Set close button in quick-commnad class
if (command.querySelector('.close-button')) continue;
var closeButton = document.createElement('span');
closeButton.className = 'close-button';
closeButton.textContent = '×';
closeButton.style.padding = '4px 8px';
// Invert color at mouse hover
closeButton.addEventListener('mouseenter', function () {
this.style.backgroundColor = '#000';
this.style.color = '#fff';
this.style.cursor = 'pointer';
});
// Revevrt color at mouse leave
closeButton.addEventListener('mouseleave', function () {
this.style.backgroundColor = '';
this.style.color = '';
this.style.cursor = 'default';
});
closeButton.addEventListener('click', handleButtonClick, true);
command.appendChild(closeButton);
}
}
function handleButtonClick() {
var titleElement = this.parentNode.getElementsByClassName('quick-command-title')[0];
var tabTitle = titleElement.textContent.trim();
removeTabFromTabTitle(tabTitle);
}
function removeTabFromTabTitle(tabTitle) {
chrome.tabs.query({}, function (tabs) {
for (var i = 0; i < tabs.length; i++) {
if (tabs[i].title !== tabTitle) continue;
chrome.tabs.remove(tabs[i].id, function () { });
return true;
}
console.log('Not found tab');
return false;
});
}
// // CSS to apply every time the inside of the modal-bg is updated
// function setQcModalCss(){
// const css = `
// /* QC Height and Width */
// .qc-modal {top: 20vh !important;}
// .quick-command-container, .quick-command-container .quick-commands > div {width:60vw !important; }
// .quick-command-container .quick-commands > div > div {max-width: 100% !important;}
// .quick-commands {max-height: 100% !important;}
// .quick-commands > div {height: 30vh !important;}
// /* Closed tabs */
// .strikethrough-text {
// text-decoration: line-through;
// opacity: 0.3;
// }
// `;
// const style = document.createElement('style');
// style.appendChild(document.createTextNode(css));
// // document.head.appendChild(style);
// }
// Observe entire html to appeare qc-modal
function startObservingModalBg() {
var targetNode = document.documentElement;
var observer = new MutationObserver(handleModalBgMutation);
const observerOptions = {
childList: true,
subtree: true
};
observer.observe(targetNode, observerOptions);
}
// observe qc-modal for refleshed commands
function handleModalBgMutation(mutationsList, observer) {
for (var mutation of mutationsList) {
if (mutation.type !== 'childList') continue;
var addedNodes = mutation.addedNodes;
for (var i = 0; i < addedNodes.length; i++) {
if (addedNodes[i].id !== 'modal-bg') continue;
addCloseButtonsToQuickCommands();
// setQcModalCss();
const observer = new MutationObserver(() => {
// setQcModalCss();
addCloseButtonsToQuickCommands()
});
const gridListElement = document.getElementById('modal-bg');
const observerOptions = {
childList: true,
subtree: true
};
observer.observe(gridListElement, observerOptions);
}
}
}
startObservingModalBg();
})();