JavaScript

Creating GUI for your desktop applications using HTML, CSS, and JavaScript

We’ll create user interface (UI) for our “Duplicate File Finder” desktop app with HTML and style it witch css. It is a very simple interface, just a log on top with Application name, version number and two button  Add folder and Start search for controlling the app behavior. The “Add folder” button will browse the file system and “Start search” will trigger the app to initiate the scanning of added folder recursively.

The Duplicate File Finder preview:
App preview
This app let you to add multiple folders in the list for scanning.

Once a folder has been added in the list, you can remove it and change its mode to excluded or included. The each folder row divided into three columns:

  1. Cross icon: Allow you to remove the folder from the list
  2. Mode: Let you to choose included or excluded
    1. included mode: Will scan the folder and its sub-folders (recursively). It is the default mode when you add a folder.
    2. excluded mode: Will not scan the folder
  3. Location: The complete path of folder.

To start developing our Duplicate File Finder app, open the main.js file and remove the default top menu bar as described below:

Remove menu bar from Electron.js app

When we build our app, the default menu won’t be there anymore, but if you wish to remove it during the development, open main.js and add mainWndow.setMenu(null)line :

function createWindow () {
  // Create the browser window.
 mainWindow = new BrowserWindow({width: 800, height: 600})

  // Disable menu
  mainWindow.setMenu(null)
  
  // and load the index.html of the app.
 mainWindow.loadURL('file://'+__dirname+'/index.html')
...

The above code will disable the default menu bar on index.html window. For multi-window app you can use the following code to disable the menu bar globally:

app.on('browser-window-created',function(event,window) {
  window.setMenu(null);
})

The directory picker

Can we get the full directory path from input type=”file”

<input type="file"> let the user choose one or more files from their device storage. To choose a directory or folder we can use webkitdirectory:

<input type="file" webkitdirectory multiple>

For security reasons browsers do not allow JavaScript to access the the File System. If we try to fetch the directory path using above code, we’ll receive the “directory name” but not the full path. To resolve this issue Electron.js provides the dialog api. https://electronjs.org/docs/api/dialog.

Electron Dialog

The Dialog is opened from Electron’s main thread (main.js file). To use dialog object from the renderer process (index.html) we need to use remote:

const {dialog} = require('electron').remote

OR

const dialog = require('electron').remote.dialog

The following code let you choose multiple directories and give their full paths in a callback function:

dialog.showOpenDialog(
 {properties: ['openDirectory', 'multiSelections']},
 (dirPaths) => {
   if (dirPaths)
    //add path in list and display on the app's browser window 
  }
)

openDirectory: Allow directories to be selected.

multiSelection: Allow multiple paths to be selected.

callback Function (dirPaths): An array of paths chosen by the user.

index.html

Open index.html file, remove the existing code and add the following code:

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <title>Duplicate file finder</title>
 <link rel="stylesheet" type="text/css" href="style.css">
 </head>
 <body>
  <div id="container">
   <div id="header"><img src="logo.png" />
    <div class="fix">
     <span class="blue">Duplicate</span> file finder<br>
     <span class="ver">Version <span class="blue">1.0.0</span></span> 
    </div>
   </div>
   <div id="menu">
    <button id="addBtn" class="btn">&#128194; Add folder</button>
    <button id="startBtn" class="btn" value="start"><span class="green">&#9654;</span> Start search</button>
   </div>
   <div id="pathsHead" class="hide">
    <span class="delDirHead"></span>
    <span class="typeDirHead">Mode</span>
    <span>Location</span>
   </div>
   <div id="paths"></div>
  </div>
  <script>require('./renderer.js')</script>
 </body>
</html>

style.css

Now create a css file style.css inside the Duplicate Files Finder project folder and add the following code.

body {font-family:Arial;font-size:1em;line-height:1.5em}
#container{min-width:700px}
#header {font-size:1.5em;font-weight:bold;line-height:0.5em}
#header .fix{position:absolute;top:50px;left:100px;text-align:right}
#header .ver{font-size:0.5em;font-weight:normal}

#menu{border-top:4px #e0ecff solid;padding:1em}
#paths{padding:0.5em 1em;height:18em;overflow:auto}
#paths div:nth-child(odd){background:#f0f0f0;}
#paths div{margin-bottom:0.3em}
.typeDir{border-radius:5px}
.delDir,.btn{font-weight:bold;text-align:center}
.btn{border:none;padding:0.7em 0;border-radius:0.7em;font-size:0.9em;width:10em}
.btn:hover,.typeDir:hover,.delDir:hover{background: #a1dbff;cursor:pointer}

.green{color:#006400}
.red, .delDir{color:#ff0000}
.blue{color:#4169E1}

#pathsHead{background:#555;padding:5px 0;padding-left:1em;color:#fff}
#pathsHead span, .typeDir, .delDir{display:inline-block}
.typeDir, .typeDirHead{width:6em;margin-right:0.8em;text-align:center;}
.delDir, .delDirHead{width:2em;margin-right:0.8em}
.typeDir, .delDir, .btn{background:#e0ecff;border:1px solid #4169e1}
.typeDirDisable{background:#eee;border:1px solid #ccc;color:#aaa}
.hide{display:none}

Summary

We edited the main.js file and removed the default menu bar by calling the setMenu(null) method.  We discussed how we can get the full path of a file or folder by using the Electron’s dialog api.  At the end, we re-created the index.html and beautify it with css using style.css.

The next page will cover: how to interact with users and respond to their actions by creating the renderer.js file.