
JS - Electron
Eueung Mulyana
http://eueung.github.io/js/electron
JS CodeLabs | Attribution-ShareAlike CC BY-SA
1 / 27
Agenda
Electron Quick Start, Boilerplate
Angular.JS Todo @ Electron
Electron + Photon
Photon Angular Todo-App
2 / 27
 Electron Quick Start
atom/electron-quick-start
3 / 27
package.json + main.js + index.html
4 / 27
package.json
{
"name":"electron-quick-start",
"version":"1.0.0",
"description":"AminimalElectronapplication",
"main":"main.js",
"scripts":{
"start":"electronmain.js"
},
"repository":{
"type":"git",
"url":"git+https://github.com/atom/electron-quick-start.git"
},
"keywords":[
"Electron","quick","start","tutorial"
],
"author":"GitHub",
"license":"CC0-1.0",
"bugs":{
"url":"https://github.com/atom/electron-quick-start/issues"
},
"homepage":"https://github.com/atom/electron-quick-start#readme"
"devDependencies":{
"electron-prebuilt":"^0.36.0"
}
}
main.js
'usestrict';
constelectron=require('electron');
constapp=electron.app;
constBrowserWindow=electron.BrowserWindow;
//--------------------------------------
letmainWindow;
//--------------------------------------
app.on('window-all-closed',function(){
if(process.platform!='darwin'){
app.quit();
}
});
//--------------------------------------
app.on('ready',function(){
mainWindow=newBrowserWindow({width:800,height:600});
mainWindow.loadURL('file://'+__dirname+'/index.html');
mainWindow.webContents.openDevTools();
mainWindow.on('closed',function(){
mainWindow=null;
});
});
5 / 27
Electron Quick Start
package.json + main.js + index.html
<!DOCTYPEhtml>
<html>
<head>
<metacharset="UTF-8">
<title>HelloWorld!</title>
<script></script>
</head>
<body>
<h1>HelloWorld!</h1>
Weareusingnode<script>
Chrome<script> </
andElectron<script>
</body>
</html>
document.write(process.versions.
document.write(process.versions.chrome)
document.write(process.versions.elect
6 / 27
 Electron Boilerplate
sindresorhus/electron-boilerplate
7 / 27
package.json + index.js + index.html + index.css
8 / 27
package.json
{
"name":"app",
"productName":"App",
"version":"0.0.0",
"description":"",
"license":"MIT",
"repository":"user/repo",
"author":{"name":"","email":"","url":""
},
"electronVersion":"0.36.0",
"scripts":{
"test":"xo",
"start":"electron.",
"build":"electron-packager.$npm_package_productName--out=dist--ignore='^/dist$'--prune--asar--all--version=$npm_p
},
"files":["index.js","index.html","index.css"
],
"keywords":["electron-app","electron"
],...
}
...
"dependencies":{
"electron-debug":"^0.5.0"
},
"devDependencies":{
"electron-packager":"^5.0.0",
"electron-prebuilt":"^0.36.0",
"xo":"^0.12.0"
},
"xo":{
"esnext":true,
"envs":["node","browser"]
}
9 / 27
index.js
'usestrict';
constelectron=require('electron');
constapp=electron.app;
//-------------------------------
require('crash-reporter').start();
require('electron-debug')();
//-------------------------------
letmainWindow;
//-------------------------------
functiononClosed(){mainWindow=null;}
//-------------------------------
functioncreateMainWindow(){
constwin=newelectron.BrowserWindow({width:800,height:
win.loadURL(`file://${__dirname}/index.html`);
win.on('closed',onClosed);
returnwin;
}
//-------------------------------
app.on('window-all-closed',()=>{
if(process.platform!=='darwin'){app.quit();}
});
//-------------------------------
app.on('activate',()=>{
if(!mainWindow){mainWindow=createMainWindow();}
});
//-------------------------------
app.on('ready',()=>{mainWindow=createMainWindow();});
10 / 27
 Angular.JS Todo @ Electron
11 / 27
12 / 27
13 / 27
{
"name":"app-03",
"version":"1.0.0",
"description":"AminimalElectronapplication",
"main":"main.js",
"devDependencies":{
"electron-prebuilt":"^0.36.0"
},
"dependencies":{
"lowdb":"^0.11.2"
}
}
package.json
main.js
'usestrict';
constelectron=require('electron');
constapp=electron.app;
constBrowserWindow=electron.BrowserWindow;
//--------------------------------------
letmainWindow;
//--------------------------------------
app.on('window-all-closed',function(){
if(process.platform!='darwin'){
app.quit();
}
});
//--------------------------------------
app.on('ready',function(){
mainWindow=newBrowserWindow({width:800,height:600});
mainWindow.loadURL('file://'+__dirname+'/angular-offline
mainWindow.setMenu(null);
mainWindow.on('closed',function(){
mainWindow=null;
});
});
14 / 27
(function(){
'usestrict';
angular.module('todoApp',[])
.controller('todoListController',[TodoListController]);
functionTodoListController(){
vartodoList=this;
todoList.todos=[];
varlow=require('lowdb');
varstorage=require('lowdb/file-sync');
todoList.db=low('app-03/db.json',{storage});
getAllTodos();
todoList.addTodo=function(){
varvarid=todoList.db('todos').size();
while(todoList.db('todos').find({id:varid})){varid+=
vardata={id:varid,text:todoList.todoText,done:
todoList.db('todos').push(data);
todoList.todos.push(data);
todoList.todoText='';
};
todoList.remaining=function(){
varcount=0;
angular.forEach(todoList.todos,function(todo){
count+=todo.done?0:1;
});
returncount;
};
angular-offline-todo.js
todoList.archive=function(){
varoldTodos=todoList.todos;
todoList.todos=[];
angular.forEach(oldTodos,function(todo){
if(!todo.done)todoList.todos.push(todo);
});
};
todoList.updDone=function(idx){
vardata=todoList.db('todos')
.chain()
.find({id:todoList.todos[idx].id})
.assign({done:todoList.todos[idx].d
.value();
};
functiongetAllTodos(){
todoList.todos=todoList.db('todos').cloneDeep();
};
}
})();
15 / 27
<!doctypehtml>
<htmlng-app="todoApp">
<head>
<scriptsrc="bower_components/angular/angular.min.js"></
<!--<scriptsrc="angular-offline-todo-service.js"></script>-->
<scriptsrc="angular-offline-todo.js"></script>
<linkrel="stylesheet"href="angular-offline-todo.css">
</head>
<body>
<h2>Todo</h2>
<divng-controller="todoListControllerastodoList">
<span>{{todoList.remaining()}}of{{todoList.todos.length}}remaining
[<ahref=""ng-click="todoList.archive()">archive</a
<ulclass="unstyled">
<ling-repeat="todointodoList.todostrackby$index"
<inputtype="checkbox"ng-model="todo.done"ng-click
<spanclass="done-{{todo.done}}">{{todo.text}}</span
</li>
</ul>
<formng-submit="todoList.addTodo()">
<inputtype="text"ng-model="todoList.todoText" size
placeholder="addnewtodohere">
<inputclass="btn-primary"type="submit"value="add"
</form>
</div>
</body>
</html>
angular-offline-todo.html
16 / 27
 Electron + Photon
17 / 27
18 / 27
Photon Template App
{
"name":"proton-template-app",
"version":"1.0.0",
"description":"AsimpletemplateappforProton",
"main":"app.js",
"author":"ConnorSears",
"scripts":{
"start":"electron."
}
}
package.json
app.js
varapp=require('app');
varBrowserWindow=require('browser-window');
//-------------------------------------
varmainWindow=null;
//-------------------------------------
app.on('window-all-closed',function(){
if(process.platform!='darwin'){
app.quit();
}
});
//-------------------------------------
app.on('ready',function(){
mainWindow=newBrowserWindow({
width:800,
height:600,
'min-width':480,
'min-height':360,
'accept-first-mouse':true,
'title-bar-style':'hidden'
});
mainWindow.loadURL('file://'+__dirname+'/index.html');
mainWindow.setMenu(null);
mainWindow.on('closed',function(){
mainWindow=null;
});
});
19 / 27
Photon Template App
package.json + app.js
index.html + js/menu.js
varremote=require('remote')
varMenu=remote.require('menu')
varMenuItem=remote.require('menu-item')
//---------------------------------
varmenu=newMenu()
menu.append(newMenuItem({
label:'Delete',
click:function(){
alert('Deleted')
}
}));
//---------------------------------
menu.append(newMenuItem({
label:'MoreInfo...',
click:function(){
alert('Hereismoreinformation')
}
}));
//---------------------------------
window.addEventListener('contextmenu',function(e){
e.preventDefault();
menu.popup(remote.getCurrentWindow());
},false);
js/menu.js
20 / 27
index.html
<!DOCTYPEhtml>
<head>
<title>Photon</title>
<linkrel="stylesheet"href="../css/photon.min.css">
<scriptsrc="js/menu.js"charset="utf-8"></script>
</head>
<body>
<divclass="window">
<headerclass="toolbartoolbar-header">
<h1class="title">Photon</h1>
</header>
<divclass="window-content">
<divclass="pane-group">
...
</div>
</div>
</div>
</body>
</html>
<html>
<divclass="panepane-smsidebar">
<navclass="nav-group">
<h5class="nav-group-title">Favorites</h5>
<spanclass="nav-group-item"><spanclass="iconicon-home"
<spanclass="nav-group-itemactive"><spanclass="iconico
<spanclass="nav-group-item"><spanclass="iconicon-downl
<spanclass="nav-group-item"><spanclass="iconicon-folde
<spanclass="nav-group-item"><spanclass="iconicon-windo
<spanclass="nav-group-item"><spanclass="iconicon-signa
<spanclass="nav-group-item"><spanclass="iconicon-monit
</nav>
</div>
<divclass="pane">
<tableclass="table-striped">
<thead>
<tr><th>Name</th><th>Kind</th><th>DateModified</th
</thead>
<tbody>
<tr><td>bars.scss</td><td>Document</td><td>Oct13,20
...
<tr><td>base.scss</td><td>Document</td><td>Oct13,20
</tbody>
</table>
</div>
21 / 27
 Photon Angular Todo-App
22 / 27
23 / 27
#angular-offline-todo.css
.margin10{
margin:10px;
width:inherit!important;
}
#app.js
mainWindow.loadURL('file://'+__dirname+'/angular-offline-todo.html'
#angular-offline-todo.js
todoList.db=low('app-05/app/db.json',{storage}); Minor Changes
app.js
angular-offline-todo.js
angular-offline-todo.css
24 / 27
angular-offline-todo.html
<!doctypehtml>
<htmlng-app="todoApp">
<head>
<scriptsrc="bower_components/angular/angular.min.js"></
<scriptsrc="angular-offline-todo.js"></script>
<linkrel="stylesheet"href="angular-offline-todo.css">
<linkrel="stylesheet"href="../css/photon.min.css">
<scriptsrc="js/menu.js"charset="utf-8"></script>
</head>
<body>
<divclass="window"ng-controller="todoListControllerastodoList"
<headerclass="toolbartoolbar-header">
<h1class="title">PhotonAngularTodo.App</h1>
</header>
...
</div>
</body>
</html>
<divclass="window-content">
<divclass="pane-group">
<tableclass="table-striped">
<thead>
<tr><th>DONE</th><th>Todo</th></tr>
</thead>
<tbody>
<trng-repeat="todointodoList.todostrackby$index"
<td><inputtype="checkbox"ng-model="todo.done"ng-c
<td><spanclass="done-{{todo.done}}">{{todo.text}}
</tr>
</tbody>
</table>
</div>
</div>
<footerclass="toolbartoolbar-footer">
<divclass="toolbar-actions">
<formng-submit="todoList.addTodo()">
<spanclass="pull-leftmargin10">{{todoList.remaining(
<inputclass="form-controlbtnbtn-primarypull-right
<inputtype="text"class="form-controlpull-rightmarg
placeholder="addnewtodohere">
</form>
</div>
</footer>
25 / 27
References
1. Electron
2. sindresorhus/awesome-electron
3. Photon · Components
26 / 27

END
Eueung Mulyana
http://eueung.github.io/js/electron
JS CodeLabs | Attribution-ShareAlike CC BY-SA
27 / 27

Develop Desktop Apps with Electron