Skip to content

Commit

Permalink
directory: de-duplicate icons, details/mobile views
Browse files Browse the repository at this point in the history
closes #968
  • Loading branch information
simov authored and dougwilson committed Dec 10, 2013
1 parent a181efd commit 81ad299
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 40 deletions.
71 changes: 60 additions & 11 deletions lib/middleware/directory.js
Expand Up @@ -70,6 +70,7 @@ exports = module.exports = function directory(root, options){
if (!root) throw new Error('directory() root path required');
var hidden = options.hidden
, icons = options.icons
, view = options.view || 'tiles'
, filter = options.filter
, root = normalize(root + sep);

Expand Down Expand Up @@ -109,7 +110,7 @@ exports = module.exports = function directory(root, options){

// not acceptable
if (!type) return next(utils.error(406));
exports[mediaType[type]](req, res, files, next, originalDir, showUp, icons, path);
exports[mediaType[type]](req, res, files, next, originalDir, showUp, icons, path, view);
});
});
};
Expand All @@ -119,7 +120,7 @@ exports = module.exports = function directory(root, options){
* Respond with text/html.
*/

exports.html = function(req, res, files, next, dir, showUp, icons, path){
exports.html = function(req, res, files, next, dir, showUp, icons, path, view){
fs.readFile(__dirname + '/../public/directory.html', 'utf8', function(err, str){
if (err) return next(err);
fs.readFile(__dirname + '/../public/style.css', 'utf8', function(err, style){
Expand All @@ -130,8 +131,8 @@ exports.html = function(req, res, files, next, dir, showUp, icons, path){
files.sort(fileSort);
if (showUp) files.unshift({ name: '..' });
str = str
.replace('{style}', style)
.replace('{files}', html(files, dir, icons))
.replace('{style}', style.concat(iconStyle(files, icons)))
.replace('{files}', html(files, dir, icons, view))
.replace('{directory}', dir)
.replace('{linked-path}', htmlPath(dir));
res.setHeader('Content-Type', 'text/html');
Expand Down Expand Up @@ -185,32 +186,80 @@ function htmlPath(dir) {
}).join(' / ');
}

/**
* Load icon images, return css string.
*/

function iconStyle (files, useIcons) {
if (!useIcons) return '';
var data = {};
var views = { tiles: [], details: [], mobile: [] };

for (var i=0; i < files.length; i++) {
var file = files[i];
if (file.name == '..') continue;

var isDir = '..' == file.name || (file.stat && file.stat.isDirectory());
var icon = isDir ? icons.folder : icons[extname(file.name)] || icons.default;

var ext = extname(file.name);
ext = isDir ? '.directory' : (icons[ext] ? ext : '.default');

if (data[icon]) continue;
data[icon] = ext + ' .name{background-image: url(data:image/png;base64,' + load(icon)+');}';
views.tiles.push('.view-tiles ' + data[icon]);
views.details.push('.view-details ' + data[icon]);
views.mobile.push('#files ' + data[icon]);
}

var style = views.tiles.join('\n')
+ '\n'+views.details.join('\n')
+ '\n@media (max-width: 768px) {\n\t'
+ views.mobile.join('\n\t')
+ '\n}';
return style;
}

/**
* Map html `files`, returning an html unordered list.
*/

function html(files, dir, useIcons) {
return '<ul id="files">' + files.map(function(file){
var icon = ''
, isDir
function html(files, dir, useIcons, view) {
return '<ul id="files" class="view-'+view+'">'
+ (view == 'details' ? (
'<li class="header">'
+ '<span class="name">Name</span>'
+ '<span class="size">Size</span>'
+ '<span class="date">Modified</span>'
+ '</li>') : '')
+ files.map(function(file){
var isDir
, classes = []
, path = dir.split('/').map(function (c) { return encodeURIComponent(c); });

if (useIcons) {
var ext = extname(file.name);
isDir = '..' == file.name || (file.stat && file.stat.isDirectory());
icon = isDir ? icons.folder : icons[extname(file.name)] || icons.default;
icon = '<img src="data:image/png;base64,' + load(icon) + '" />';
ext = isDir ? '.directory' : (icons[ext] ? ext : '.default');
classes.push('icon');
classes.push(ext.replace('.',''));
}

path.push(encodeURIComponent(file.name));

var date = file.name == '..' ? ''
: file.stat.mtime.toDateString()+' '+file.stat.mtime.toLocaleTimeString();
var size = file.name == '..' ? '' : file.stat.size;

return '<li><a href="'
+ utils.normalizeSlashes(normalize(path.join('/')))
+ '" class="'
+ classes.join(' ') + '"'
+ ' title="' + file.name + '">'
+ icon + file.name + '</a></li>';
+ '<span class="name">'+file.name+'</span>'
+ '<span class="size">'+size+'</span>'
+ '<span class="date">'+date+'</span>'
+ '</a></li>';

}).join('\n') + '</ul>';
}
Expand Down
3 changes: 2 additions & 1 deletion lib/public/directory.html
Expand Up @@ -2,6 +2,7 @@
<html>
<head>
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>listing directory {directory}</title>
<style>{style}</style>
<script>
Expand Down Expand Up @@ -44,7 +45,7 @@
var classes = this.getClasses().filter(function(curr){
return curr != name;
});
this.setAttribute('class', classes);
this.setAttribute('class', classes.join(' '));
};

return el;
Expand Down
172 changes: 144 additions & 28 deletions lib/public/style.css
@@ -1,5 +1,10 @@
body {
* {
margin: 0;
padding: 0;
outline: 0;
}

body {
padding: 80px 100px;
font: 13px "Helvetica Neue", "Lucida Grande", "Arial";
background: #ECE9E9 -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ECE9E9));
Expand All @@ -9,7 +14,6 @@ body {
-webkit-font-smoothing: antialiased;
}
h1, h2, h3 {
margin: 0;
font-size: 22px;
color: #343434;
}
Expand All @@ -21,21 +25,15 @@ h1 {
font-size: 60px;
}
h2 {
margin-top: 10px;
margin-top: 10px;
}
h3 {
margin: 5px 0 10px 0;
padding-bottom: 5px;
border-bottom: 1px solid #eee;
font-size: 18px;
}
ul {
margin: 0;
padding: 0;
}
ul li {
margin: 5px 0;
padding: 3px 8px;
list-style: none;
}
ul li:hover {
Expand Down Expand Up @@ -64,46 +62,35 @@ a:hover {
color: #303030;
}
#stacktrace {
margin-top: 15px;
margin-top: 15px;
}
.directory h1 {
margin-bottom: 15px;
font-size: 18px;
}
ul#files {
width: 100%;
height: 500px;
height: 100%;
overflow: hidden;
}
ul#files li {
padding: 0;
}
ul#files li img {
position: absolute;
top: 5px;
left: 5px;
float: left;
width: 30%;
line-height: 25px;
margin: 1px;
}
ul#files li a {
position: relative;
display: block;
margin: 1px;
width: 30%;
height: 25px;
line-height: 25px;
text-indent: 8px;
float: left;
border: 1px solid transparent;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
overflow: hidden;
text-overflow: ellipsis;
}
ul#files li a.icon {
text-indent: 25px;
white-space: nowrap;
}
ul#files li a:focus,
ul#files li a:hover {
outline: none;
background: rgba(255,255,255,0.65);
border: 1px solid #ececec;
}
Expand Down Expand Up @@ -139,3 +126,132 @@ ul#files li a.highlight {
width: 120px;
opacity: 1.0;
}

/*views*/
#files span {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
text-indent: 10px;
}
#files .name {
background-repeat: no-repeat;
}
#files .icon .name {
text-indent: 28px;
}

/*tiles*/
.view-tiles .name {
width: 100%;
background-position: 8px 5px;
}
.view-tiles .size,
.view-tiles .date {
display: none;
}

/*details*/
ul#files.view-details li {
float: none;
display: block;
width: 90%;
}
ul#files.view-details li.header {
height: 25px;
background: #000;
color: #fff;
font-weight: bold;
}
.view-details .header {
border-radius: 5px;
}
.view-details .name {
width: 60%;
background-position: 8px 5px;
}
.view-details .size {
width: 10%;
}
.view-details .date {
width: 30%;
}
.view-details .size,
.view-details .date {
text-align: right;
direction: rtl;
}

/*mobile*/
@media (max-width: 768px) {
body {
font-size: 13px;
line-height: 16px;
padding: 0;
}
#search {
position: static;
width: 100%;
font-size: 2em;
line-height: 1.8em;
text-indent: 10px;
border: 0;
border-radius: 0;
padding: 10px 0;
margin: 0;
}
#search:focus {
width: 100%;
border: 0;
opacity: 1;
}
.directory h1 {
font-size: 2em;
line-height: 1.5em;
color: #fff;
background: #000;
padding: 15px 10px;
margin: 0;
}
ul#files {
border-top: 1px solid #cacaca;
}
ul#files li {
float: none;
width: auto !important;
display: block;
border-bottom: 1px solid #cacaca;
font-size: 2em;
line-height: 1.2em;
text-indent: 0;
margin: 0;
}
ul#files li:nth-child(odd) {
background: #e0e0e0;
}
ul#files li a {
height: auto;
border: 0;
border-radius: 0;
padding: 15px 10px;
}
ul#files li a:focus,
ul#files li a:hover {
border: 0;
}
#files .header,
#files .size,
#files .date {
display: none !important;
}
#files .name {
float: none;
display: inline-block;
width: 100%;
text-indent: 0;
background-position: 0 0;
}
#files .icon .name {
text-indent: 41px;
}
}

0 comments on commit 81ad299

Please sign in to comment.