diff --git a/auto-style.js b/auto-style.js
index 3b6da76..c65a5bc 100644
--- a/auto-style.js
+++ b/auto-style.js
@@ -3,6 +3,7 @@ function setStyle(theme) {
let documentBody = document.body;
let inputFieldStyle = document.getElementById("find-input").style;
let generalBodyStyle = document.body.style;
+ let modeIndicatorStyle = document.getElementById("mode-indicator").style;
let sSheets = document.styleSheets[0];
// General body style
@@ -15,6 +16,7 @@ function setStyle(theme) {
// default text color
generalBodyStyle.color = theme.colors.toolbar_field_text;
inputFieldStyle.color = theme.colors.toolbar_field_text;
+ modeIndicatorStyle.color = theme.colors.toolbar_field_text;
}
// Input field style
diff --git a/background.js b/background.js
index e3171e2..7466a6d 100644
--- a/background.js
+++ b/background.js
@@ -1,49 +1,20 @@
var opened = false;
-var pluginPanelId = null
-
-async function find(query) {
- browser.runtime.sendMessage({msg: "clear-results"});
-
- if (!query)
- return;
-
- let this_tab_url = browser.runtime.getURL("find-tab.html");
- let tabs = await browser.tabs.query({}).then(allTabs => findMatchingTab(query, allTabs, this_tab_url));
-
-}
-
-async function findMatchingTab(query, allTabs, thisTabUrl) {
- const regex = RegExp(query);
- for (let tab of allTabs) { // just search through tabs titles for now, maybe add in depth tab searching later?
- if (tab.url == thisTabUrl)
- {
- continue;
- }
- if (regex.test(tab.title) || tab.title.toLowerCase().includes(query)) {
- browser.runtime.sendMessage({
- msg: "found-result",
- title: tab.title,
- id: tab.id,
- url: tab.url,
- query: query
- });
- }
- }
- browser.runtime.sendMessage({
- msg: "results-complete"
- });
- //console.log("Handled find " + query);
-}
+var pluginPanelId = null;
+var tabsFromLastWindow = null;
+var tabsFromAllWindows = null;
function createNewWindow() {
let createData = {
type: "detached_panel",
url: "find-tab.html",
width: window.screen.width / 2, // find reasonable size
- height: window.screen.height / 2
+ height: window.screen.height / 2,
+ // current bug 1271047 prevents from pos being set
+ left: window.screen.width / 2, // position in the centre
+ top: window.screen.height / 2
};
let pluginPanel = browser.windows.create(createData);
- waitForPanelId(pluginPanel)
+ waitForPanelId(pluginPanel);
opened = true;
};
@@ -51,19 +22,48 @@ async function waitForPanelId(pluginPanel) {
pluginPanelId = await pluginPanel.then(pluginPanel => pluginPanel.id);
}
+// Requests tabs, from all windows and the current one.
+async function getTabs() {
+ await browser.tabs.query({currentWindow: true}).then((allT) => {tabsFromLastWindow = allT});
+ await browser.tabs.query({currentWindow: false}).then((allT) => {tabsFromAllWindows = allT});
+}
+
+function sendTabs() {
+ browser.runtime.sendMessage({
+ msg: "all-tabs",
+ tabsLastW: tabsFromLastWindow,
+ tabsAllW: tabsFromAllWindows
+ });
+}
+
// Listeners
browser.browserAction.onClicked.addListener(() => {
// check if already open
if (opened)
return;
createNewWindow();
+ getTabs();
});
browser.commands.onCommand.addListener(function (command) {
- if (opened)
- return;
-
if (command == "toggle-plugin") {
- createNewWindow();
+ // Toggle the plugin on and off
+ if (opened)
+ {
+ browser.windows.remove(pluginPanelId);
+ // opened is set to false and handled by find-tab.js by handlePanelClose
+ }
+ else {
+ createNewWindow();
+ getTabs();
+ }
}
-});
\ No newline at end of file
+ else if (command == "close-Tab") {
+ if (opened)
+ browser.runtime.sendMessage({msg: "close-tab"});
+ }
+ else if (command == "toggle-search-mode") {
+ if (opened)
+ browser.runtime.sendMessage({msg: "toggle-search-mode"});
+ }
+});
diff --git a/find-tab.html b/find-tab.html
index f40ceb8..0402b88 100644
--- a/find-tab.html
+++ b/find-tab.html
@@ -10,10 +10,11 @@
diff --git a/find-tab.js b/find-tab.js
index ea0747a..9d7fc84 100644
--- a/find-tab.js
+++ b/find-tab.js
@@ -1,15 +1,16 @@
let backgroundPage = browser.extension.getBackgroundPage();
let find_input = document.getElementById("find-input");
let result_list = document.getElementById("result-list"); // to avoid FF errors, they have to be obtained each time
+let modeIndicator = document.getElementById("mode-indicator");
+let tabsListLastWindow = null;
+let tabsListAllWindows = null;
-let timeout = null;
+let searchThroughLastWindow = false;
let selected = null;
-// hack to ignore reload on 'Enter' Keypress in form field
-document.getElementById("find-form").addEventListener("keypress", function(e) {
- if (e.key === "Enter")
- e.preventDefault();
-});
+// request all tabs from the bg script
+backgroundPage.sendTabs();
+
document.getElementById("find-form").addEventListener("keyup", function(e) {
if (e.key !== "Enter" && e.key !== "Escape" && e.key !== "ArrowUp" && e.key !== "ArrowDown") {
@@ -26,11 +27,16 @@ document.getElementById("find-form").addEventListener("keyup", function(e) {
if (tab.classList.contains("Selected")) {
result_list.removeChild(tab);
i -= 1;
- selected = {
- "idx" : 0,
- "val" : result_list.firstChild
- };
- selected.val.classList.add("Selected");
+ if (result_list.childElementCount)
+ {
+ selected = {
+ "idx" : 0,
+ "val" : result_list.firstChild
+ };
+ selected.val.classList.add("Selected");
+ } else {
+ selected = null;
+ }
} else {
result_list.removeChild(tab);
i -= 1;
@@ -40,27 +46,16 @@ document.getElementById("find-form").addEventListener("keyup", function(e) {
}
} else {
selected = null;
- clearTimeout(timeout);
-
- timeout = setTimeout(() => {
- //console.log("Pre find " + find_input.value);
- backgroundPage.find(find_input.value);
- }, 300);
+ find(find_input.value);
}
- e.preventDefault();
- }
-})
-
-document.addEventListener("keydown", function(e) {
- if (e.key === "ArrowUp" || e.key === "ArrowDown") {
- e.preventDefault();
}
-})
+});
// prevent popping up the textinput
-document.addEventListener("keyup", function(e) {
+document.addEventListener("keydown", function(e) {
switch (e.key) {
case "Enter":
+ e.preventDefault();
if (selected)
{
//navigate to selected
@@ -85,18 +80,20 @@ document.addEventListener("keyup", function(e) {
break;
case "Escape":
+ e.preventDefault();
closeWidget();
break;
case "ArrowUp":
+ e.preventDefault();
selectPreceding();
break;
case "ArrowDown":
+ e.preventDefault();
selectSuceeding();
break;
}
- e.preventDefault();
});
window.addEventListener("keyup", function(e) {
@@ -106,60 +103,137 @@ window.addEventListener("keyup", function(e) {
e.preventDefault();
});
-function handleMessage(request, sender, sendResponse) {
- if (request.msg === "clear-results") {
- result_list.innerHTML = "";
- }
- if (request.msg === "found-result") {
- let tr = document.createElement("tr");
- let title = document.createElement("td");
- let url = document.createElement("td");
- let id = document.createElement("td");
- title.innerText = request.title;
- url.innerText = request.url;
- id.innerText = request.id;
- tr.appendChild(title);
- tr.appendChild(url);
- tr.appendChild(id);
- result_list.appendChild(tr);
+function find(query) {
+ result_list.innerHTML = '';
+
+ if (!query)
+ return;
+
+ let this_tab_url = browser.runtime.getURL("find-tab.html");
+ let tabsList = searchThroughLastWindow ? tabsListLastWindow : tabsListAllWindows;
+ const regex = RegExp(query);
+
+ for (let tab of tabsList)
+ {
+ if (tab.url == this_tab_url)
+ continue;
+
+ if (regex.test(tab.title) || tab.title.toLowerCase().includes(query)) {
+ let tr = document.createElement("tr");
+ let title = document.createElement("td");
+ let url = document.createElement("td");
+ let id = document.createElement("td");
+ title.innerText = tab.title;
+ url.innerText = tab.url;
+ id.innerText = tab.id;
+ tr.appendChild(title);
+ tr.appendChild(url);
+ tr.appendChild(id);
+ result_list.appendChild(tr);
+ }
}
- if (request.msg === "results-complete") {
- //console.log("Obtained results for: " + request.query)
- //console.log(result_list);
- //console.log(result_list.hasChildNodes());
- //console.log(selected);
- if (result_list.hasChildNodes()) {
+ if (result_list.hasChildNodes()) {
selected = {
"idx" : 0,
"val" : result_list.firstChild
- };
+ }
//console.log("SELECTED: " + selected.val.innerText);
// add Class Selected for CSS highlight
selected.val.classList.add("Selected");
+ selected.val.scrollIntoView(true);
+ }
+}
+
+function handleMessage(request, sender, sendResponse) {
+ if(request.msg == "all-tabs")
+ {
+ tabsListLastWindow = request.tabsLastW;
+ tabsListAllWindows = request.tabsAllW;
+ }
+ else if (request.msg == "close-tab") {
+ let currentSelected = selected.val;
+ index = 0;
+ for (index; index el.id === idCurrentSelected), 1);
+ let indexInCurrWindow = tabsListLastWindow.findIndex(el => el.id === idCurrentSelected);
+
+ if (indexInCurrWindow !== -1) {
+ tabsListLastWindow.splice(indexInCurrWindow, 1);
+ }
+
+ if (index > 0) {
+ selectPreceding();
+ }
+ else if (result_list.hasChildNodes()) {
+ selected = {
+ "idx" : 0,
+ "val" : result_list.firstChild
+ }
+ //console.log("SELECTED: " + selected.val.innerText);
+ // add Class Selected for CSS highlight
+ selected.val.classList.add("Selected");
}
-}
+ }
+ else if (request.msg == "toggle-search-mode") {
+ updateSearchMode();
+ }
+}
+
+function updateSearchMode() {
+ searchThroughLastWindow = !searchThroughLastWindow;
+ find_input.placeholder = 'Search through: ' + (searchThroughLastWindow ? 'Last Window' : 'All Windows');
+ modeIndicator.innerText = searchThroughLastWindow ? 'C' : 'A';
+ find(find_input.value);
+}
function selectPreceding() {
- if (selected.idx !== 0) {
- selected.val.classList.remove("Selected"); //remove Selected class from prev selected
+ if (selected.idx > 0) {
+ selected.val.classList.remove("Selected"); //remove Selected class from prev selected
selected = {
"idx" : selected.idx -= 1,
"val" : result_list.children[selected.idx]
};
selected.val.classList.add("Selected"); // add Selected class to new selected
+ selected.val.scrollIntoView(true);
+ }
+ else if (result_list.childElementCount > 1) {
+ selected.val.classList.remove("Selected");
+ selected = {
+ "idx" : result_list.childElementCount - 1,
+ "val" : result_list.lastChild
+ };
+ selected.val.classList.add("Selected"); // add Selected class to new selected
+ selected.val.scrollIntoView(true);
}
}
function selectSuceeding() {
let size = result_list.childElementCount;
- if (selected.idx !== size -1) {
+ if (selected.idx < size - 1) {
selected.val.classList.remove("Selected"); // remove Selected class from prev selected
selected = {
"idx" : selected.idx += 1,
"val" : result_list.children[selected.idx]
};
selected.val.classList.add("Selected"); // add Selected class to new selected
+ selected.val.scrollIntoView(true);
+ }
+ else if (result_list.childElementCount > 1) {
+ selected.val.classList.remove("Selected");
+ selected = {
+ "idx" : 0,
+ "val" : result_list.firstChild
+ };
+ selected.val.classList.add("Selected"); // add Selected class to new selected
+ selected.val.scrollIntoView(true);
}
}
@@ -171,12 +245,10 @@ function closeWidget() {
function handlePanelClose(windowId) {
if (backgroundPage.pluginPanelId == windowId)
backgroundPage.opened = false;
-
};
// sort the list on the fly, most occurences matching listed first, how about near matches?
browser.runtime.onMessage.addListener(handleMessage);
-
browser.windows.onRemoved.addListener(handlePanelClose);
// On lost focus, close
-//window.addEventListener("blur", closeWidget);
\ No newline at end of file
+window.addEventListener("blur", closeWidget);
\ No newline at end of file
diff --git a/manifest.json b/manifest.json
index 1a29fdb..eb17a15 100644
--- a/manifest.json
+++ b/manifest.json
@@ -20,7 +20,7 @@
"32": "search.svg"
}
},
- "version": "1.0",
+ "version": "1.1.1",
"browser_specific_settings": {
"gecko": {
"strict_min_version": "65.0"
@@ -32,6 +32,18 @@
"default": "Ctrl+Space"
},
"description": "Send a 'toggle-plugin' event to turn it on and off"
+ },
+ "close-Tab": {
+ "suggested_key": {
+ "default": "Ctrl+E"
+ },
+ "description": "Send a 'close-Tab' event to close the currently selected tab"
+ },
+ "toggle-search-mode": {
+ "suggested_key": {
+ "default": "Ctrl+Shift+Space"
+ },
+ "description": "Send a 'toggle-search-mode' event to alter between searching through all windows and the last window"
}
}
- }
\ No newline at end of file
+ }
diff --git a/stylesheet.css b/stylesheet.css
index 26b9b80..230ac9b 100644
--- a/stylesheet.css
+++ b/stylesheet.css
@@ -13,6 +13,12 @@ hr {
margin-right: 0.5%;
}
+div#mode-indicator {
+ display: inline-block;
+ font-weight: bold;
+ width: 1%;
+}
+
table#result-list {
padding-left: 0.5%;
padding-right: 0.5%;
@@ -23,6 +29,8 @@ table#result-list tr {
display: block;
border-radius: 0.15em;
width: 100%;
+ /*offset when scrolling at the top*/
+ scroll-margin-top:2.2em;
}
table#result-list td:nth-child(1) {
@@ -34,15 +42,25 @@ table#result-list td:nth-child(1) ~ td {
display: none;
}
+form#find-form {
+ /* keeps the input field at the top
+ higher z-index => drawn on top of the rest*/
+ position: sticky;
+ top:0;
+ z-index:2;
+}
+
div#form {
padding-top: 0.5%;
padding-bottom: 0.5%;
+ padding-left: 0.5%;
+ padding-right: 0.5%;
}
input#find-input {
border: none;
- width: 99%;
- display: block;
+ width: 98%;
+ display: inline-block;
margin-left: auto;
margin-right: auto;
}