Reputation: 93
I'm new to Electron Js and I am trying to make a custom titlebar as a project. I made the titlebar in a html page called nav.html
and imported it in index.html
(the main page)
nav.html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
button {
margin: 0;
padding: 0;
border: none;
outline: none;
background-color: transparent;
height: 35px;
}
.header {
background-color: black;
color: white;
overflow: hidden;
}
#title {
width: 80%;
-webkit-app-region: drag;
-webkit-user-select: none;
user-select: none;
}
svg.restore {
fill: rgb(255, 255, 255) !important;
width: 15px;
height: 15px;
padding: 10px 14px;
}
svg.restore:hover {
fill: rgb(255, 255, 255) !important;
background-color: #5e5e5e !important;
}
button.minimize {
padding: 3.5px 16px;
color: white;
}
button.minimize:hover {
background-color: #5e5e5e !important;
}
.maximize {
cursor: default;
fill: white;
padding: 10px 14px;
height: 15px;
width: 15px;
display: none;
}
.maximize:hover {
background-color: #5e5e5e !important;
color: white;
}
button.close {
padding: 3.3px 14px;
color: white;
}
button.close:hover {
background-color: red !important;
}
</style>
</head>
<body>
<div
class="header"
style="display: flex; align-items: center; justify-content: space-between;"
>
<div id="title"></div>
<div style="display: flex; align-items: center; justify-content: center;">
<button
style="font-size: 25px; cursor: default"
class="minimize"
id="minimize"
>
-
</button>
<button>
<svg
width="25px"
height="25px"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
style="cursor: default"
class="restore"
id="restore"
>
<path
d="M352,153H40.247a24.028,24.028,0,0,0-24,24V458a24.028,24.028,0,0,0,24,24H352a24.028,24.028,0,0,0,24-24V177A24.028,24.028,0,0,0,352,153Zm-8,32v45.22H48.247V185ZM48.247,450V262.22H344V450Z"
class="ci-primary"
/>
<path
d="M472,32H152a24.028,24.028,0,0,0-24,24v65h32V64H464V339.143H408v32h64a24.028,24.028,0,0,0,24-24V56A24.028,24.028,0,0,0,472,32Z"
class="ci-primary"
/>
</svg>
<svg
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
class="maximize"
id="maximize"
>
<path
d="M896 85.333333H128a42.666667 42.666667 0 0 0-42.666667 42.666667v768a42.666667 42.666667 0 0 0 42.666667 42.666667h768a42.666667 42.666667 0 0 0 42.666667-42.666667V128a42.666667 42.666667 0 0 0-42.666667-42.666667z m-42.666667 768H170.666667V426.666667h682.666666z m0-512H170.666667V170.666667h682.666666z"
/>
</svg>
</button>
<button
style="font-size: 25px; cursor: default"
class="close"
id="close"
>
×
</button>
</div>
</div>
<script>
document.getElementById("title").innerHTML = document.title;
// ipc connection between main.js and nav.html buttons to mainpulate the function of the window asynchronously
const { ipcRenderer } = require("electron");
const ipc = ipcRenderer;
const restore = document.querySelector("#restore");
const maximize = document.querySelector("#maximize");
const minimize = document.querySelector("#minimize");
const closeBtn = document.querySelector("#close");
// close the window
closeBtn.onclick = function(){
ipc.send("closeApp");
console.log('mama earth');
}
restore.onclick = function () {
maximize.style.display = "block";
restore.style.display = "none";
};
maximize.onclick = function () {
restore.style.display = "block";
maximize.style.display = "none";
};
</script>
</body>
</html>
I have added inline styles as well as style tag and script tag in the same html document
Problem comes when I am not able to use require('electron')
in a script tag. I am trying to make the top window buttons and using the ipcRenderer
to process them to main.js.
Main.js :
const { app, BrowserWindow , ipcMain} = require('electron')
const path = require('path')
const ipc = ipcMain
function createWindow() {
const win = new BrowserWindow({
width: 1200,
height: 700,
center: true,
minHeight: 700,
minWidth: 1200,
frame: false,
webPreferences: {
nodeIntegration: true,
contextIsolation : true,
devTools: true,
preload: path.join(__dirname, 'preload.js'),
}
})
win.loadFile('index.html')
//close window function
ipc.on('closeApp', () => {
console.log('app is closed')
win.close()
})
}
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
I have just added the index.html and preload.js for no confussion :
index.html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<title>Home</title>
<link rel="stylesheet" href="style.css" />
<script src="main.js"></script>
</head>
<body>
<iframe id="nav-placeholder" src="nav.html" width="100%" style="border: none;height: 35px !important;" loading="eager"></iframe>
<a href="nav.html">Go to nav page</a>
</body>
</html>
Preload.js :
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const type of ['chrome', 'node', 'electron']) {
replaceText(`${type}-version`, process.versions[type])
}
})
I tried using require JS but I had no idea how to do it. If anyone has an answer to it or can guide me through the error it would be highly appreciatable!
Thank you in advance!
Upvotes: 0
Views: 2658
Reputation: 9489
@Dony is right, in today's Electron world, using require
in the HTML page is a big no no. (disclaimer, I wrote the blog post that he's linking to).
I'm curious reading your question, are you looking to create a navigation or a menu? If it's a menu, then Electron has support to do this natively through the Menu class.
You ask a really great question, because setting this up in a secure way requires some communication between the renderer and main processes. My template uses this pattern within the menu to update the app's language, alongside this package.
I unfortunately don't have enough time to thoroughly go into detail at this moment, but will suggest you first take a peak at whether it may be a menu you are looking to add your functionality to. If it is, I hope some of my repository's files can direct you in the place where you can see how to set up the link between the js and the html file within an Electron application.
I'm also currently in the process of writing an "Ultimate Electron guide" that would cover these topics in a thorough blog post. I estimate it's many weeks out as I intend to go in great detail to explain Electron concepts such as this one. It'll be up on https://www.debugandrelease.com/ when I post it (subscribe if you'd like an email when it goes out).
Upvotes: 0
Reputation: 1979
You probably read some deprecated articles or forum posts, because calling electron from an HTML file is now an "old way" to use the ipcRenderer.
For security reasons, electron
should not be directly accessible from your HTML page. You should only require ipcRenderer
from your preload script, where you can put it in a method. Then, you can access your method by sharing it with the contextBridge.
I know this might be confusing at the beginning. You can find a well documented example here about What/How to use the ContextBridge https://github.com/reZach/secure-electron-template/blob/master/docs/newtoelectron.md
Upvotes: 1