An improvement upon the previous example. Files and folders are now sorted alphabetically, icons reflect the file's type, files are represented as big tiles with previews in case of image files.
Last active
October 20, 2015 14:47
-
-
Save nitaku/ce69c0cb655897b95daf to your computer and use it in GitHub Desktop.
Virtual Filesystem UI 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# data | |
ramona = {id: 0, name: 'ramona flowers.png', type: 'image'} | |
bttf_cover = {id: 1, name: 'Back to the Future - Cover.jpg', type: 'image'} | |
photos = { | |
id: 10, | |
name:'Photos', | |
subfolders: [], | |
files: [] | |
} | |
pictures = { | |
id: 2, | |
name:'Pictures', | |
subfolders: [photos], | |
files: [ramona, {id: 9, name: 'chibi miku.jpg', type: 'image'}, bttf_cover] | |
} | |
movies = { | |
id: 3, | |
name:'Movies', | |
subfolders: [], | |
files: [{id: 6, name: 'Back to the Future.mkv', type: 'video'}, bttf_cover] | |
} | |
documents = { | |
id: 4, | |
name:'Documents', | |
subfolders: [photos], | |
files: [ramona, {id: 12, name: 'money money money.txt', type: 'text'},{id: 13, name: 'pitfalls.pdf', type: 'pdf'}] | |
} | |
music = { | |
id: 14, | |
name:'Music', | |
subfolders: [], | |
files: [{id: 15, name: 'Tell your world (初音ミク).mp3', type: 'audio'}, {id: 16, name: 'Surrounded (Dream Theater).mp3', type: 'audio'}] | |
} | |
root = { | |
id: 5, | |
subfolders: [pictures, movies, documents, music], | |
files: [{id: 7, name: 'vmlinuz'}] | |
} | |
index_n_sort = (node) -> | |
if node.index? | |
return | |
node.index = {} | |
node.subfolders.forEach (sf) -> node.index[sf.name] = sf | |
node.files.forEach (f) -> node.index[f.name] = f | |
node.subfolders.sort (a,b) -> d3.ascending(a.name, b.name) | |
node.files.sort (a,b) -> d3.ascending(a.name, b.name) | |
node.subfolders.forEach (sf) -> | |
index_n_sort(sf) | |
index_n_sort(root) | |
# status | |
open_folders = [root] | |
cd = (sf_name) -> | |
open_folders.push open_folders[open_folders.length-1].index[sf_name] | |
redraw() | |
cd__ = () -> | |
if open_folders.length > 1 | |
open_folders.pop() | |
redraw() | |
cut_path = (folder) -> | |
if open_folders.length is 1 or open_folders[open_folders.length-1].id is folder.id | |
redraw() | |
return | |
open_folders.pop() | |
cut_path(folder) | |
# UI | |
cwd = d3.select('#cwd') | |
subfolders_container = cwd.append('div') | |
files_container = cwd.append('div') | |
up = d3.select('#up_btn') | |
breadcrumb = d3.select('#breadcrumb') | |
up.on 'click', () -> cd__() | |
redraw = () -> | |
cwd_data = open_folders[open_folders.length-1] | |
subfolders = subfolders_container.selectAll('.subfolder') | |
.data(cwd_data.subfolders, (d) -> d.id ) | |
subfolders.enter().append('div') | |
.attr | |
class: 'subfolder node' | |
.html (d) -> '<i class="icon fa fa-fw fa-folder"></i> '+d.name | |
.on 'click', (d) -> cd d.name | |
subfolders.exit().remove() | |
subfolders.order() | |
files = files_container.selectAll('.file') | |
.data(cwd_data.files, (d) -> d.id ) | |
enter_files = files.enter().append('div') | |
.attr | |
class: 'file node' | |
enter_previews = enter_files.append('div') | |
.attr | |
class: 'preview' | |
enter_previews.each (d) -> | |
if d.type is 'image' | |
d3.select(this) | |
.style | |
'background-image': "url(#{encodeURI(d.name)})" | |
else | |
d3.select(this) | |
.html (d) -> "<i class='icon fa fa-4x fa-file#{if d.type? then '-'+d.type else ''}-o'></i>" | |
enter_files.append('div') | |
.attr | |
class: 'filename' | |
.html (d) -> "<span>#{d.name}</span>" | |
files.exit().remove() | |
files.order() | |
path_items = breadcrumb.selectAll('.path_item') | |
.data(open_folders, (d) -> d.id ) | |
path_items.enter().append('div') | |
.attr | |
class: 'path_item' | |
.html (d) -> '<span>' + if d.name? then d.name else 'Home' + '</span>' | |
.on 'click', (d) -> cut_path(d) | |
path_items.exit().remove() | |
redraw() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
html, body { | |
margin: 0; | |
padding: 0; | |
font-family: sans-serif; | |
font-size: 14px; | |
color: #333; | |
background: #DDD; | |
} | |
#cwd { | |
padding: 4px; | |
} | |
#bar { | |
padding: 6px; | |
box-shadow: 0px 0px 6px #777; | |
background: #EEE; | |
} | |
#bar > * { | |
display: inline-block; | |
} | |
.path_item { | |
display: inline-block; | |
margin-right: 6px; | |
cursor: pointer; | |
} | |
.path_item:not(:first-child)::before { | |
content: '\f054'; | |
margin-right: 6px; | |
font-family: 'FontAwesome'; | |
color: #999; | |
font-size: 10px; | |
} | |
.path_item:hover > span { | |
text-decoration: underline; | |
} | |
.node { | |
margin: 4px; | |
background: white; | |
} | |
.subfolder { | |
padding: 6px; | |
} | |
.subfolder:hover { | |
cursor: pointer; | |
background: #FFF4DC; | |
} | |
#cwd .icon { | |
color: #777; | |
} | |
.file { | |
display: inline-block; | |
width: 142px; | |
height: 132px; | |
text-align: center; | |
vertical-align: text-top; | |
position: relative; | |
} | |
.file .icon { | |
margin-top: 16px; | |
} | |
.preview { | |
width: 100%; | |
background-size: 100%; | |
height: 90px; | |
} | |
.filename { | |
box-sizing: border-box; | |
padding: 4px; | |
background: #EEE; | |
position: absolute; | |
bottom: 0; | |
width: 100%; | |
height: 42px; | |
line-height: 32px; | |
} | |
.filename > span { | |
padding: 0; | |
display: inline-block; | |
vertical-align: middle; | |
line-height: normal; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>Virtual Filesystem UI 2</title> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<link rel="stylesheet" href="index.css"> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css"> | |
</head> | |
<body> | |
<div id="bar"> | |
<button id="up_btn"><i class="icon fa fa-level-up"></i></button> | |
<div id="breadcrumb"></div> | |
</div> | |
<div id="cwd"></div> | |
<script src="index.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Generated by CoffeeScript 1.10.0 | |
(function() { | |
var breadcrumb, bttf_cover, cd, cd__, cut_path, cwd, documents, files_container, index_n_sort, movies, music, open_folders, photos, pictures, ramona, redraw, root, subfolders_container, up; | |
ramona = { | |
id: 0, | |
name: 'ramona flowers.png', | |
type: 'image' | |
}; | |
bttf_cover = { | |
id: 1, | |
name: 'Back to the Future - Cover.jpg', | |
type: 'image' | |
}; | |
photos = { | |
id: 10, | |
name: 'Photos', | |
subfolders: [], | |
files: [] | |
}; | |
pictures = { | |
id: 2, | |
name: 'Pictures', | |
subfolders: [photos], | |
files: [ | |
ramona, { | |
id: 9, | |
name: 'chibi miku.jpg', | |
type: 'image' | |
}, bttf_cover | |
] | |
}; | |
movies = { | |
id: 3, | |
name: 'Movies', | |
subfolders: [], | |
files: [ | |
{ | |
id: 6, | |
name: 'Back to the Future.mkv', | |
type: 'video' | |
}, bttf_cover | |
] | |
}; | |
documents = { | |
id: 4, | |
name: 'Documents', | |
subfolders: [photos], | |
files: [ | |
ramona, { | |
id: 12, | |
name: 'money money money.txt', | |
type: 'text' | |
}, { | |
id: 13, | |
name: 'pitfalls.pdf', | |
type: 'pdf' | |
} | |
] | |
}; | |
music = { | |
id: 14, | |
name: 'Music', | |
subfolders: [], | |
files: [ | |
{ | |
id: 15, | |
name: 'Tell your world (初音ミク).mp3', | |
type: 'audio' | |
}, { | |
id: 16, | |
name: 'Surrounded (Dream Theater).mp3', | |
type: 'audio' | |
} | |
] | |
}; | |
root = { | |
id: 5, | |
subfolders: [pictures, movies, documents, music], | |
files: [ | |
{ | |
id: 7, | |
name: 'vmlinuz' | |
} | |
] | |
}; | |
index_n_sort = function(node) { | |
if (node.index != null) { | |
return; | |
} | |
node.index = {}; | |
node.subfolders.forEach(function(sf) { | |
return node.index[sf.name] = sf; | |
}); | |
node.files.forEach(function(f) { | |
return node.index[f.name] = f; | |
}); | |
node.subfolders.sort(function(a, b) { | |
return d3.ascending(a.name, b.name); | |
}); | |
node.files.sort(function(a, b) { | |
return d3.ascending(a.name, b.name); | |
}); | |
return node.subfolders.forEach(function(sf) { | |
return index_n_sort(sf); | |
}); | |
}; | |
index_n_sort(root); | |
open_folders = [root]; | |
cd = function(sf_name) { | |
open_folders.push(open_folders[open_folders.length - 1].index[sf_name]); | |
return redraw(); | |
}; | |
cd__ = function() { | |
if (open_folders.length > 1) { | |
open_folders.pop(); | |
return redraw(); | |
} | |
}; | |
cut_path = function(folder) { | |
if (open_folders.length === 1 || open_folders[open_folders.length - 1].id === folder.id) { | |
redraw(); | |
return; | |
} | |
open_folders.pop(); | |
return cut_path(folder); | |
}; | |
cwd = d3.select('#cwd'); | |
subfolders_container = cwd.append('div'); | |
files_container = cwd.append('div'); | |
up = d3.select('#up_btn'); | |
breadcrumb = d3.select('#breadcrumb'); | |
up.on('click', function() { | |
return cd__(); | |
}); | |
redraw = function() { | |
var cwd_data, enter_files, enter_previews, files, path_items, subfolders; | |
cwd_data = open_folders[open_folders.length - 1]; | |
subfolders = subfolders_container.selectAll('.subfolder').data(cwd_data.subfolders, function(d) { | |
return d.id; | |
}); | |
subfolders.enter().append('div').attr({ | |
"class": 'subfolder node' | |
}).html(function(d) { | |
return '<i class="icon fa fa-fw fa-folder"></i> ' + d.name; | |
}).on('click', function(d) { | |
return cd(d.name); | |
}); | |
subfolders.exit().remove(); | |
subfolders.order(); | |
files = files_container.selectAll('.file').data(cwd_data.files, function(d) { | |
return d.id; | |
}); | |
enter_files = files.enter().append('div').attr({ | |
"class": 'file node' | |
}); | |
enter_previews = enter_files.append('div').attr({ | |
"class": 'preview' | |
}); | |
enter_previews.each(function(d) { | |
if (d.type === 'image') { | |
return d3.select(this).style({ | |
'background-image': "url(" + (encodeURI(d.name)) + ")" | |
}); | |
} else { | |
return d3.select(this).html(function(d) { | |
return "<i class='icon fa fa-4x fa-file" + (d.type != null ? '-' + d.type : '') + "-o'></i>"; | |
}); | |
} | |
}); | |
enter_files.append('div').attr({ | |
"class": 'filename' | |
}).html(function(d) { | |
return "<span>" + d.name + "</span>"; | |
}); | |
files.exit().remove(); | |
files.order(); | |
path_items = breadcrumb.selectAll('.path_item').data(open_folders, function(d) { | |
return d.id; | |
}); | |
path_items.enter().append('div').attr({ | |
"class": 'path_item' | |
}).html(function(d) { | |
return '<span>' + (d.name != null ? d.name : 'Home' + '</span>'); | |
}).on('click', function(d) { | |
return cut_path(d); | |
}); | |
return path_items.exit().remove(); | |
}; | |
redraw(); | |
}).call(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment