diff --git a/globe.png b/globe.png
new file mode 100644
index 0000000..659e79c
Binary files /dev/null and b/globe.png differ
diff --git a/index.html b/index.html
index b841af5..c27bd28 100644
--- a/index.html
+++ b/index.html
@@ -54,7 +54,7 @@
background-color: black;
border-right: 0;
font-weight: bold;
- line-height: 30px;
+ line-height: 40px;
vertical-align: middle;
white-space: nowrap;
overflow: hidden
@@ -157,6 +157,87 @@
background-color: black;
}
+#zoomMenu{
+ position: fixed;
+ left: 15px;
+ top: 70px;
+ width: 250px;
+ height: 40px;
+ z-index: 999;
+ background-color: black;
+ display: none;
+ border: 1px solid yellowgreen
+}
+
+#currentZoom {
+ position: absolute;
+ top: 10px;
+ left: 5px;
+ outline: 0;
+ color: yellowgreen;
+ font-family: 'Fira Code', monospace;
+}
+
+#findMenu{
+ position: fixed;
+ right: 15px;
+ top: 70px;
+ width: 250px;
+ height: 40px;
+ z-index: 999;
+ background-color: black;
+ display: none;
+ border: 1px solid yellowgreen
+}
+
+#findInput {
+ width: 150px;
+ height: 20px;
+ border: 0;
+ border-bottom: 2px solid yellowgreen;
+ position: absolute;
+ top: 10px;
+ left: 5px;
+ outline: 0;
+ background-color: black;
+ color: yellowgreen;
+ font-family: 'Fira Code', monospace;
+}
+
+#findInput:focus{
+ outline: 0
+}
+
+.findMenuButton{
+ background-color: black;
+ color: yellowgreen;
+ border: 1px solid yellowgreen;
+}
+
+.findMenuButtonDiv{
+ position: absolute;
+ right: 5px;
+ top: 10px;
+}
+
+.favicon{
+ width: 15px;
+ height: 15px;
+ margin-left: -10px;
+ padding: 4px;
+ display: inline-block;
+}
+
+#contextmenu, #contextmenuSelect {
+ position: absolute;
+ background-color: black;
+ color: yellowgreen;
+ z-index: 999;
+ top:0;
+ left: 0;
+ display: none;
+}
+
@media screen and (max-width: 300px){
nav{
display: none;
@@ -183,7 +264,7 @@
-
diff --git a/main.js b/main.js
index cdacdc7..f0df91a 100644
--- a/main.js
+++ b/main.js
@@ -1,4 +1,4 @@
-const { app, BrowserWindow, ipcMain, Menu, MenuItem } = require("electron");
+const { app, BrowserWindow, ipcMain, Menu, MenuItem, webContents } = require("electron");
const path = require("path");
const createWindow = () => {
@@ -23,6 +23,7 @@ const createWindow = () => {
}]
}))
win.setMenu(menu);
+ // win.setMenu(null);
win.loadFile("index.html");
};
diff --git a/renderer.js b/renderer.js
index 4e0a682..25cfa05 100644
--- a/renderer.js
+++ b/renderer.js
@@ -44,7 +44,7 @@ function closeTabHandler(e) {
}
-function setTabActive(toSet) {
+async function setTabActive(toSet) {
// set currently active tab inactive
let webviews = document.getElementById("webviews").children;
let tabs = document.getElementById("tabs").children;
@@ -71,6 +71,14 @@ function setTabActive(toSet) {
[...webviews].find(view => view.dataset.index == toSet.dataset.index).style.height = "100%";
// activeView.style.flex = "0 1";
activeTabIndex = toSet.dataset.index;
+
+ let url = document.getElementById("url");
+ if (toSet.dataset.url == "file://" + await window.electronAPI.dirname() + "/newtab.html"){
+ url.value = "";
+ } else {
+ url.value = toSet.dataset.url;
+ }
+
}
function closeTab(tab) {
@@ -90,7 +98,7 @@ function closeTab(tab) {
tabs.removeChild(tab);
//delete webview
// webviews.removeChild([...webviews].find(view => view.dataset.index == tab.dataset.index));
- [...webviews].find(view => view.dataset.index == tab.dataset.index).remove();
+ [...webviews.children].find(view => view.dataset.index == tab.dataset.index).remove();
}
function handleReload(e) {
@@ -108,10 +116,11 @@ function createNewTab(url) {
let tabs = document.getElementById("tabs");
let newTab = elementFromHTML(
- `
`
+ `
`
);
newTab.addEventListener("click", setTabActiveHandler);
newTab.dataset.index = totalTabs;
+ newTab.dataset.url = url;
tabs.appendChild(newTab);
let closeButton = elementFromHTML('
')
@@ -128,7 +137,7 @@ function createNewTab(url) {
function createNewWebview(url, tab) {
let webviews = document.getElementById("webviews");
let newview = elementFromHTML(
- `
`
+ `
`
);
newview.style = `width: 100%;
height: calc(100vh - 60px);
@@ -137,26 +146,116 @@ function createNewWebview(url, tab) {
top: 60px;
left: 0`;
-newview.addEventListener("did-finish-load", ()=>{
- tab.children[0].innerHTML = newview.getTitle()
+newview.addEventListener("did-finish-load", async ()=>{
+ tab.children[1].innerHTML = newview.getTitle();
+ let domain = new URL(newview.getURL());
+ domain = domain.hostname;
+ if (url == "file://" + await window.electronAPI.dirname() + "/newtab.html") {
+ tab.children[0].src = "globe.png"
+ } else {
+ tab.children[0].src = `http://www.google.com/s2/favicons?domain=${domain}`;
+ }
+})
+
+newview.addEventListener("context-menu", (e) => {
+ let contextmenu = document.getElementById("contextmenu");
+ let contextmenuSelect = document.getElementById("contextmenuSelect");
+ if (e.params.selectionText != ""){
+ contextmenuSelect.style.display = "block";
+ contextmenu.style.display = "none";
+ contextmenuSelect.style.top = e.params.y + "px";
+ contextmenuSelect.style.left = e.params.x + "px";
+} else {
+ contextmenu.style.display = "block";
+ contextmenuSelect.style.display = "none";
+ contextmenu.style.top = e.params.y + "px";
+ contextmenu.style.left = e.params.x + "px";
+ }
+});
+
+newview.addEventListener("ipc-message", (e)=>{
+ let contextmenu = document.getElementById("contextmenu");
+ let contextmenuSelect = document.getElementById("contextmenuSelect");
+ if (e.args.length != 0) { // if is a keypress
+ let event = new KeyboardEvent('keydown', {
+ code: e.args[0],
+ key: e.args[1],
+ shiftKey: e.args[2],
+ altKey: e.args[3],
+ ctrlKey: e.args[4],
+ metaKey: e.args[5],
+ repeat: e.args[6]
+ });
+ shortcutHandler(event);
+ } else { // if is a click
+ contextmenuSelect.style.display = "none";
+ contextmenu.style.display = "none";
+ }
})
+
+
newview.dataset.index = totalTabs;
+
totalTabs++;
webviews.appendChild(newview);
}
-
-document.onkeydown = async function (e) {
- if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() == "t") {
+document.onkeydown = shortcutHandler;
+async function shortcutHandler(e) {
+ let contextmenu = document.getElementById("contextmenu");
+ let contextmenuSelect = document.getElementById("contextmenuSelect");
+ let webviews = document.getElementById("webviews").children;
+ let currView = [...webviews].find(view => view.dataset.index == activeTabIndex);
+ if ((e.ctrlKey || e.metaKey) && e.key == "t") {
createNewTab("file://" + await window.electronAPI.dirname() + "/newtab.html");
- } else if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() == "w") {
+ contextmenuSelect.style.display = "none";
+ contextmenu.style.display = "none";
+ } else if ((e.ctrlKey || e.metaKey) && e.key == "w") {
let tabs = document.getElementById("tabs").children;
closeTab([...tabs].find(tab => tab.dataset.index == activeTabIndex))
- } else if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() == "r") {
+ contextmenuSelect.style.display = "none";
+ contextmenu.style.display = "none";
+ } else if ((e.ctrlKey || e.metaKey) && e.key == "r") {
handleReload(e);
- } else if (e.ctrlKey && e.shiftKey && e.key.toLowerCase() == "i") {
- let webviews = document.getElementById("webviews").children;
- [...webviews].find(view => view.dataset.index == activeTabIndex).openDevTools();
+ contextmenuSelect.style.display = "none";
+ contextmenu.style.display = "none";
+ } else if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key == "I") {
+ currView.openDevTools();
+ contextmenuSelect.style.display = "none";
+ contextmenu.style.display = "none";
+ } else if ((e.ctrlKey || e.metaKey) && e.key == "f") {
+ document.getElementById("findMenu").style.display = "block";
+ document.getElementById("findInput").focus();
+ contextmenuSelect.style.display = "none";
+ contextmenu.style.display = "none";
+ } else if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key == "V") {
+ currView.pasteAndMatchStyle();
+ contextmenuSelect.style.display = "none";
+ contextmenu.style.display = "none";
+ } else if (e.key == "Escape") {
+ currView.stopFindInPage("keepSelection");
+ document.getElementById("findMenu").style.display = "none";
+ contextmenuSelect.style.display = "none";
+ contextmenu.style.display = "none";
+ } else if ((e.ctrlKey || e.metaKey) && e.key == "p") {
+ currView.printToPDF({});
+ contextmenuSelect.style.display = "none";
+ contextmenu.style.display = "none";
+ } else if ((e.ctrlKey || e.metaKey) && e.key == "=") {
+ currView.setZoomFactor(currView.getZoomFactor()+0.1)
+ document.getElementById("currentZoom").innerText = Math.round(currView.getZoomFactor() * 100) + "%"
+ document.getElementById("zoomMenu").style.display = "block";
+ setTimeout(() => {document.getElementById("zoomMenu").style.display = "none"}, 3000)
+ contextmenuSelect.style.display = "none";
+ contextmenu.style.display = "none";
+ } else if ((e.ctrlKey || e.metaKey) && e.key == "-") {
+ currView.setZoomFactor(currView.getZoomFactor()-0.1)
+ document.getElementById("currentZoom").innerText = Math.round(currView.getZoomFactor() * 100) + "%"
+ document.getElementById("zoomMenu").style.display = "block";
+ setTimeout(() => {document.getElementById("zoomMenu").style.display = "none"}, 3000)
+ contextmenuSelect.style.display = "none";
+ contextmenu.style.display = "none";
}
+
};
(async function() {
@@ -167,9 +266,7 @@ document.onkeydown = async function (e) {
document.getElementById("url").addEventListener("keydown", (e) => {
- console.log(e.key)
let tabs = document.getElementById("tabs").children;
- console.log(e.target.value)
if (e.key == "Enter") {
// change src of webview
// change tab name
@@ -191,11 +288,60 @@ document.getElementById("url").addEventListener("keydown", (e) => {
}
});
+document.getElementById("findInput").addEventListener("input", () => {
+ let findInput = document.getElementById("findInput");
+ let webviews = document.getElementById("webviews").children;
+ [...webviews].find(view => view.dataset.index == activeTabIndex).findInPage(findInput.value, {
+ forward: true,
+ findNext: true,
+ matchCase: false
+ });
+})
+
+document.getElementById("findNext").addEventListener("click", () => {
+ let webviews = document.getElementById("webviews").children;
+ let findInput = document.getElementById("findInput");
+ [...webviews].find(view => view.dataset.index == activeTabIndex).findInPage(findInput.value, {
+ forward: true,
+ findNext: false,
+ matchCase: false
+ });
+})
+
+document.getElementById("findPrev").addEventListener("click", () => {
+ let webviews = document.getElementById("webviews").children;
+ let findInput = document.getElementById("findInput");
+ [...webviews].find(view => view.dataset.index == activeTabIndex).findInPage(findInput.value, {
+ forward: false,
+ findNext: false,
+ matchCase: false
+ });
+})
+
+document.getElementById("closeFindMenu").addEventListener("click", () => {
+ document.getElementById("findMenu").style.display = "none";
+})
+
+document.body.addEventListener("click", (e) => {
+ contextmenu = document.getElementById("contextmenu");
+ contextmenuSelect = document.getElementById("contextmenuSelect");
+ if (e.target != contextmenu && e.target != contextmenuSelect) {
+ contextmenu.style.display = "none";
+ contextmenuSelect.style.display = "none";
+ }
+})
+
-// implement keboard shortcutrs: undo, redo, cut, copy, paste, select all, zoom in, zoom out
-//change url when change tab
-//fix webview component not deleting
+
+
+
+//draggable tabs
// bookmarks
-//setings with themes
//autofill in url bar
-// fix when closing tabs it deselects/ selects first
\ No newline at end of file
+// fix when closing tabs it selects first tab
+//right click dropdown menu
+// fix print to pdf
+
+//buttons in zoom menu
+//settings menu with themes and history
+//open
\ No newline at end of file
diff --git a/viewPreload.js b/viewPreload.js
new file mode 100644
index 0000000..9528b18
--- /dev/null
+++ b/viewPreload.js
@@ -0,0 +1,21 @@
+window.onload = function () {
+ const { ipcRenderer } = require("electron");
+
+ document.body.addEventListener("click", (e) => {
+ ipcRenderer.sendToHost("ipc-message");
+ });
+
+ document.onkeydown = function handle(e) {
+ console.log(e);
+ ipcRenderer.sendToHost(
+ "ipc-message",
+ e.code,
+ e.key,
+ e.shiftKey,
+ e.altKey,
+ e.ctrlKey,
+ e.metaKey,
+ e.repeat
+ );
+ };
+};