第二篇博客中我们可以看到我们构建的桌面应用会显示我们的文件及文件夹。
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;
100%;
z-index: 2;
}
#current-folder {
float: left;
color: white;
background: rgba(0,0,0,0.2);
padding: 0.5em 1em;
min- 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;
6em;
height: 6em;
text-align: center;
}
.item .filename {
padding-top: 1em;
font-size: 10pt;
}
#search {
float: right;
padding: 0.5em;
min- 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>>这本书