跟我一起使用electron搭建一个文件浏览器应用吧(三)
第二篇博客中我们可以看到我们构建的桌面应用会显示我们的文件及文件夹。
In the second blog, we can see that the desktop application we built will display our files and folders.
但是有一点就是它不能进行点击查看里面的内容,接下来我们继续改造我们的项目吧~
But one thing is that it can't Click to see the contents. Next, let's continue to transform our project.
第一步重构代码,将代码进行逻辑分组
The first step is to refactor the code and group it logically.
fileSystem.js
'use strict';
const async = require('async');
const fs = require('fs');
const osenv = require('osenv');
const path = require('path');
let shell;
if (process.versions.electron) {
shell = require('electron').shell;
} else {
shell = window.require('nw.gui').Shell;
}
function getUsersHomeFolder() {
return osenv.home();
}
function getFilesInFolder(folderPath, cb) {
fs.readdir(folderPath, cb);
}
function inspectAndDescribeFile(filePath, cb) {
let result = { file: path.basename(filePath), path: filePath, type: '' };
fs.stat(filePath, (err, stat) => {
if (err) {
cb(err);
} else {
if (stat.isFile()) {
result.type = 'file';
}
if (stat.isDirectory()) {
result.type = 'directory';
}
cb(err, result);
}
});
}
function inspectAndDescribeFiles(folderPath, files, cb) {
async.map(files, (file, asyncCb) => {
let resolvedFilePath = path.resolve(folderPath, file);
inspectAndDescribeFile(resolvedFilePath, asyncCb);
}, cb);
}
function openFile(filePath) {
shell.openItem(filePath);
}
module.exports = {
getUsersHomeFolder,
getFilesInFolder,
inspectAndDescribeFiles,
openFile
};
userInterface.js
'use strict';
let document;
const fileSystem = require('./fileSystem');
const search = require('./search');
const path = require('path');
function displayFolderPath(folderPath) {
document.getElementById('current-folder')
.innerHTML = convertFolderPathIntoLinks(folderPath);
bindCurrentFolderPath();
}
function clearView() {
const mainArea = document.getElementById('main-area');
let firstChild = mainArea.firstChild;
while (firstChild) {
mainArea.removeChild(firstChild);
firstChild = mainArea.firstChild;
}
}
function loadDirectory(folderPath) {
return function (window) {
if (!document) document = window.document;
search.resetIndex();
displayFolderPath(folderPath);
fileSystem.getFilesInFolder(folderPath, (err, files) => {
clearView();
if (err) {
return alert('Sorry, we could not load your folder');
}
fileSystem.inspectAndDescribeFiles(folderPath, files, displayFiles);
});
};
}
function displayFile(file) {
const mainArea = document.getElementById('main-area');
const template = document.querySelector('#item-template');
let clone = document.importNode(template.content, true);
search.addToIndex(file);
clone.querySelector('img').src = `images/${file.type}.svg`;
clone.querySelector('img').setAttribute('data-filePath', file.path);
if (file.type === 'directory') {
clone.querySelector('img')
.addEventListener('dblclick', () => {
loadDirectory(file.path)();
}, false);
} else {
clone.querySelector('img')
.addEventListener('dblclick', () => {
fileSystem.openFile(file.path);
},
false);
}
clone.querySelector('.filename').innerText = file.file;
mainArea.appendChild(clone);
}
function displayFiles(err, files) {
if (err) {
return alert('Sorry, we could not display your files');
}
files.forEach(displayFile);
}
function bindDocument (window) {
if (!document) {
document = window.document;
}
}
function bindSearchField(cb) {
document.getElementById('search').addEventListener('keyup', cb, false);
}
function filterResults(results) {
const validFilePaths = results.map((result) => { return result.ref; });
const items = document.getElementsByClassName('item');
for (var i = 0; i < items.length; i++) {
let item = items[i];
let filePath = item.getElementsByTagName('img')[0]
.getAttribute('data-filepath');
if (validFilePaths.indexOf(filePath) !== -1) {
item.style = null;
} else {
item.style = 'display:none;';
}
}
}
function resetFilter() {
const items = document.getElementsByClassName('item');
for (var i = 0; i < items.length; i++) {
items[i].style = null;
}
}
function convertFolderPathIntoLinks (folderPath) {
const folders = folderPath.split(path.sep);
const contents = [];
let pathAtFolder = '';
folders.forEach((folder) => {
pathAtFolder += folder + path.sep;
contents.push(`<span class="path" data-path="${pathAtFolder.slice(0,-1)}">${folder}</span>`);
});
return contents.join(path.sep).toString();
}
function bindCurrentFolderPath() {
const load = (event) => {
const folderPath = event.target.getAttribute('data-path');
loadDirectory(folderPath)();
};
const paths = document.getElementsByClassName('path');
for (var i = 0; i < paths.length; i++) {
paths[i].addEventListener('click', load, false);
}
}
module.exports = { bindDocument, displayFiles, loadDirectory, bindSearchField, filterResults, resetFilter };
app.js
'use strict';
const fileSystem = require('./fileSystem');
const userInterface = require('./userInterface');
const search = require('./search');
function main() {
userInterface.bindDocument(window);
let folderPath = fileSystem.getUsersHomeFolder();
userInterface.loadDirectory(folderPath)(window);
userInterface.bindSearchField((event) => {
const query = event.target.value;
if (query === '') {
userInterface.resetFilter();
} else {
search.find(query, userInterface.filterResults);
}
});
}
window.onload = main;
app.css
body {
padding: 0;
margin: 0;
font-family: 'Helvetica','Arial','sans';
}
#toolbar {
top: 0px;
position: fixed;
background: red;
width: 100%;
z-index: 2;
}
#current-folder {
float: left;
color: white;
background: rgba(0,0,0,0.2);
padding: 0.5em 1em;
min-width: 10em;
border-radius: 0.2em;
margin: 1em;
}
#main-area {
clear: both;
margin: 2em;
margin-top: 3em;
z-index: 1;
}
.item {
position: relative;
float: left;
padding: 1em;
margin: 1em;
width: 6em;
height: 6em;
text-align: center;
}
.item .filename {
padding-top: 1em;
font-size: 10pt;
}
#search {
float: right;
padding: 0.5em;
min-width: 10em;
border-radius: 3em;
margin: 2em 1em;
border: none;
outline: none;
}
span.path:hover, img:hover {
opacity: 0.7;
cursor: pointer;
}
index.html
<html>
<head>
<title>Lorikeet</title>
<link rel="stylesheet" href="app.css" />
<script src="app.js"></script>
</head>
<body>
<template id="item-template">
<div class="item">
<img class="icon" />
<div class="filename"></div>
</div>
</template>
<div id="toolbar">
<div id="current-folder"></div>
<input type="search" id="search" results="5" placeholder="Search" />
</div>
<div id="main-area"></div>
</body>
</html>
search.js
'use strict';
const lunr = require('lunr');
let index;
function resetIndex() {
index = lunr(function () {
this.field('file');
this.field('type');
this.ref('path');
});
}
function addToIndex(file) {
index.add(file);
}
function find(query, cb) {
if (!index) {
resetIndex();
}
const results = index.search(query);
cb(results);
}
module.exports = { addToIndex, find, resetIndex };
安装lunr.js他支持对文件夹和文件的搜索
Install lunr. js, which supports searching for folders and files
cnpm install lunr --save
这个lunr的版本号最好为0.7.2,不用最新的。
The lunr version number is best 0.7.2, not the latest.
运行项目我们可以看到效果为
We can see the effect of running the project is as follows

本文的例子学习自 <<跨平台桌面应用开发基于Electron与NW.js>>这本书
跟我一起使用electron搭建一个文件浏览器应用吧(三)的更多相关文章
- 跟我一起使用electron搭建一个文件浏览器应用吧(二)
这个文件浏览器应用可以具备以下两种功能噢- This file browser application can have the following two functions. 一:用户浏览文件夹和 ...
- 跟我一起使用electron搭建一个文件浏览器应用吧(四)
在软件的世界里面,创建一个新项目很容易,但是坚持将他们开发完成并发布却并非易事.分发软件就是一个分水岭, 分水岭的一边是那些完成的被全世界用户在用的软件,而另外一边则是启动了无数项目却没有一个完成的. ...
- Electron构建一个文件浏览器应用(一)
在window.mac.linux系统中,他们都有一个共同之处就是以文件夹的形式来组织文件的.并且都有各自的组织方式,以及都有如何查询和显示哪些文件给用户的方法.那么从现在开始我们来学习下如何使用El ...
- Electron构建一个文件浏览器应用(二)
在前一篇文章我们已经学习到了使用Electron来构建我们的文件浏览器了基础东西了,我们之前已经完成了界面功能和显示文件或文件夹的功能了,想看之前文章,请点击这个链接 .现在我们需要在之前的基础上来 ...
- Electron为文件浏览器创建图标(三)
在前面的文章中,请看之前文章,我们已经完成了使用 electron做文件浏览器这么一个应用,现在我们需要为应用创建图标操作.为应用创建图标以后,我们就可以从计算机中与其他应用区分开来,如果我们自己会做 ...
- django 搭建一个投票类网站(三)
之前修改index的视图的代码,工作原理是先试用loader方法加载视图,然后HTTPResponse方法初始化一个HTTPResponse对象并返回给浏览器.对于很多django视图来说,他们的工作 ...
- 如何搭建一个WEB服务器项目(三)—— 实现安卓端联网登录
安卓端调用服务器登录函数进行验证登录 观前提示:本系列文章有关服务器以及后端程序这些概念,我写的全是自己的理解,并不一定正确,希望不要误人子弟.欢迎各位大佬来评论区提出问题或者是指出错误,分享宝贵经验 ...
- 比nerdtree更好的文件浏览器:vimfiler
通过:VimFilerExplorer来打开一个文件浏览器 h:收起 t:展开 -:close 回车:进入或展开 空格:收起
- php写的非常简单的文件浏览器
php写的非常简单的一个文件浏览器,仅供参考. <?php /** * php文件浏览程序函数 showDir() * * $dirName 输入目录路径,默认php文件一级目录,不需输入: * ...
随机推荐
- Linux下绑定网卡的操作记录
公司采购的服务器安装了双网卡,并进行bond网卡绑定设置,网卡绑定mode共有七种(0~6) bond0.bond1.bond2.bond3.bond4.bond5.bond6. 第一种模式:mod= ...
- xcode archive 去掉dsym文件和添加dsym文件
打包慢,让人发狂!!! 所以我们尝试的去掉一些测试时候用不到的东西 比如DSYM: 这DSYM是收集奔溃的.在测试的时候不需要这些东西的所以去掉就好: 项目 Build Settings -> ...
- 把cnblogs变成简书 - cnblogs博客自定义皮肤css样式
吐槽 博客园cnblogs作为老牌的IT技术博客类网站,为广大的开发者提供了非常不错的学习交流平台. 虽然博客内容才是重点,但是如果有赏心悦目的页面不更好吗! cnblogs可以更换博客模板,并且提供 ...
- <<梦断代码>>阅读笔记三
看完了这最后三分之一的<梦断代码>,意味着这本软件行业的著作已经被我粗略地过了一遍. 在这最后三分之一的内容中,我深入了解了在大型软件项目的运作过程中存在的困难和艰辛.一个大型软件项目的成 ...
- zookeeper安装和使用 windows环境(转)
原文地址: http://blog.csdn.net/tlk20071/article/details/52028945 简介 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是G ...
- Beta阶段敏捷冲刺四
一.举行站立式会议 1.当天站立式会议照片一张 2.团队成员报告 林楚虹 (1) 昨天已完成的工作:导入到数据表 (2) 今天计划完成的工作:排行榜功能 (3) 工作中遇到的困难:转为csv文件时音标 ...
- HTML 选择器
c56 div:nth-of-type(1) { margin-left: 12px; margin-top: 25px; } .c56 div:nth-of-type(2) { margin-top ...
- Issue: business key in a call activiti
https://community.alfresco.com/thread/221280-business-key-in-a-call-activity 这个帖子有一些讨论和回复. https://c ...
- js选择排序。
<script> , , , , , , , ]; ; j<len; j++ ){ // 假设min为最小值 var minIndex = j; var min = arr[j]; ...
- 服务器RAID设置以及简单理解
备注: 适用于测试环境,生产环境暂时未验证 1. RAID种类 最高性能的RAID0 完全拆分所有的IO 不进行校验 但是单盘损坏, 数据完全丢失 最高损耗的RAID1 损失一半的存储容量, 做镜像, ...