1
0
mirror of https://github.com/lrsjng/h5ai.git synced 2025-09-03 10:53:08 +02:00

Compare commits

...

13 Commits
v0.5.2 ... v0.9

Author SHA1 Message Date
Lars Jung
5245b131b8 Forgot to build target. 2011-07-18 23:24:26 +02:00
Lars Jung
0293d54789 Finally decided to release v0.9. Totally flushed by the feedback of the last 2 days. Thanks. See README.md for changes. 2011-07-18 23:22:24 +02:00
Lars Jung
0d4edcb047 Lots of changes. See README.md changelog. 2011-07-08 03:32:23 +02:00
Lars Jung
a339814582 Updated screenshots. 2011-07-07 02:59:10 +02:00
Lars Jung
8eac4ca133 Removed shadows. Reworked tree side bar. 2011-07-07 02:26:07 +02:00
Lars Jung
e4646734f2 Added localization. 2011-07-05 01:39:45 +02:00
Lars Jung
e54abe08ca Added folder effects to details and icons view. Moved some icons. 2011-07-04 20:14:24 +02:00
Lars Jung
faaddd8d60 Remove screenshots. 2011-07-04 16:31:05 +02:00
Lars Jung
d599425452 Some comments and documentation. 2011-07-04 16:26:35 +02:00
Lars Jung
3e6197d2fc Added comments in options.js. 2011-07-04 12:51:34 +02:00
Lars Jung
ecf93da505 Forgot to remove local options. 2011-07-04 02:24:12 +02:00
Lars Jung
e91a127771 Forgot to remove local options. 2011-07-04 02:23:43 +02:00
Lars Jung
b8fba3ac8e Added basic options support. Refactored js. 2011-07-04 02:18:27 +02:00
45 changed files with 1412 additions and 757 deletions

View File

@@ -1,14 +1,14 @@
# h5ai v0.5.2   ·   a beautified Apache index # h5ai v0.9   ·   a beautified Apache index
## Screenshots ## Screenshots
<a href="http://github.com/lrsjng/h5ai/raw/master/resources/h5ai-v0.4-details.png" target="_blank"> <a href="http://larsjung.de/h5ai/sample/screenshots/h5ai-v0.7-details.png" target="_blank">
<img src="http://github.com/lrsjng/h5ai/raw/master/resources/h5ai-v0.4-details.png" width="400px" alt="screenshot" title="screenshot" style="display: inline" /> <img src="http://larsjung.de/h5ai/sample/screenshots/h5ai-v0.7-details.png" width="400px" alt="screenshot" title="details view" style="display: inline" />
</a> </a>
&#160; &#160; &#160; &#160; &#160; &#160;
<a href="http://github.com/lrsjng/h5ai/raw/master/resources/h5ai-v0.4-icons.png" target="_blank"> <a href="http://larsjung.de/h5ai/sample/screenshots/h5ai-v0.7-icons.png" target="_blank">
<img src="http://github.com/lrsjng/h5ai/raw/master/resources/h5ai-v0.4-icons.png" width="400px" alt="screenshot" title="screenshot" style="display: inline" /> <img src="http://larsjung.de/h5ai/sample/screenshots/h5ai-v0.7-icons.png" width="400px" alt="screenshot" title="icons view" style="display: inline" />
</a> </a>
@@ -24,9 +24,9 @@ Everything you need is located in folder `target`.
* Copy folder `h5ai` to the web-root directory of your server or alternativly set an alias `/h5ai/` to * Copy folder `h5ai` to the web-root directory of your server or alternativly set an alias `/h5ai/` to
this folder. this folder.
* Add the content of file `dot.htaccess` to the `.htaccess` file inside the directory * Add the content of file `dot.htaccess` to the `.htaccess` file inside the directory you want to be
you want to be styled (you might have to create this file). This directory and any subdirectories will be styled (you might have to create this file). This directory and any subdirectories will be styled by h5ai.
styled by h5ai. * Adjust `options.js` inside the `h5ai` folder to your needs. Defaults will be fine for a start.
Optionally add `h5ai.header.html` and/or `h5ai.footer.html` files to any of the styled folders to [display Optionally add `h5ai.header.html` and/or `h5ai.footer.html` files to any of the styled folders to [display
custom top or bottom sections](http://larsjung.de/h5ai/sample/customize). The content of those files custom top or bottom sections](http://larsjung.de/h5ai/sample/customize). The content of those files
@@ -47,6 +47,51 @@ please respect their rights.
## Changelog ## Changelog
### v0.9
*2011-07-18*
* linked hover states between crumb, extended view and tree
* fixed size of tree view (now there's a ugly scrollbar, hopefully will be fixed)
* refactored js to improve performance and cleaned code
* added caching for folder status codes and content
* added fr translation by [Nicolas](http://github.com/Nicosmos)
* added nl translation by [Stefan de Konink](http://github.com/skinkie)
* added sv translation by Oscar Carlsson
### v0.8
*2011-07-08*
* removed slashes from folder labels
* optionally rename parent folder entries to real folder names, see `options.js`
* long breadcrumbs (multiple rows) no longer hide content
* error folder icons are opaque now
* refactored js a lot (again...)
### v0.7
*2011-07-07*
* removed shadows
* smarter tree side bar
### v0.6
*2011-07-05*
* refactored js
* added localization, see `options.js`
### v0.5.3
*2011-07-04*
* refactored js
* added basic options support via `options.js`
* commented `options.js`
* optional tree sidebar
### v0.5.2 ### v0.5.2
*2011-07-02* *2011-07-02*

View File

@@ -3,7 +3,7 @@ custom = true
# project # project
project.name = h5ai project.name = h5ai
project.version = 0.5.2 project.version = 0.9
# src # src

View File

@@ -2,6 +2,7 @@
<project <project
name="h5ai" name="h5ai"
basedir="." basedir="."
default="build"
xmlns:scripp="antlib:de.larsjung.scripp.ant" xmlns:scripp="antlib:de.larsjung.scripp.ant"
> >
<target name="init"> <target name="init">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

View File

@@ -12,16 +12,15 @@
white-space: nowrap; white-space: nowrap;
clear: both; clear: both;
&.header a { &.header {
a, a:active, a:visited {
padding-bottom: 18px; padding-bottom: 18px;
color: #555; color: #555;
text-decoration: none;
opacity: 0.4; opacity: 0.4;
cursor: pointer; cursor: pointer;
.transition( all 0.2s ease-in-out ); .transition( all 0.2s ease-in-out );
&:visited {
color: #555;
}
&:hover { &:hover {
color: #555; color: #555;
opacity: 0.9; opacity: 0.9;
@@ -32,18 +31,39 @@
padding: 0 8px; padding: 0 8px;
} }
} }
}
&.entry { &.entry {
border-bottom: 1px solid #ddd; border-bottom: 1px solid #ddd;
a { a, a:active, a:visited {
display: block; display: block;
color: #555;
text-decoration: none;
cursor: pointer; cursor: pointer;
&:hover { &:hover, &.hover {
background-color: #f6f6f6; background-color: #f6f6f6;
color: #e80; color: #e80;
} }
} }
&.error {
a, a:active, a:visited {
color: #aaa;
.label {
.hint {
margin-left: 12px;
font-size: 0.9em;
color: #c55;
}
}
&:hover, &.hover {
opacity: 1;
background-color: #f6f6f6;
color: #e80;
}
}
}
} }
.icon, .label, .date, .size { .icon, .label, .date, .size {
padding: 6px; padding: 6px;
@@ -65,17 +85,17 @@
} }
.label { .label {
display: block; display: block;
margin: 0 220px 0 24px; margin: 0 270px 0 24px;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-align: left; text-align: left;
} }
.date { .date {
position: absolute; position: absolute;
right: 70px; right: 100px;
top: 0; top: 0;
text-align: right; text-align: right;
width: 140px; width: 160px;
white-space: nowrap; white-space: nowrap;
} }
.size { .size {
@@ -83,7 +103,7 @@
right: 0; right: 0;
top: 0; top: 0;
text-align: right; text-align: right;
width: 50px; width: 80px;
white-space: nowrap; white-space: nowrap;
} }
} }
@@ -100,7 +120,7 @@
#extended.icons-view { #extended.icons-view {
display: none; display: none;
padding: 10px; padding: 3px;
border: 1px solid #eee; border: 1px solid #eee;
border-radius: 15px; border-radius: 15px;
@@ -116,7 +136,7 @@
&.entry { &.entry {
float: left; float: left;
a { a, a:active, a:visited {
display: block; display: block;
margin: 8px; margin: 8px;
padding: 8px; padding: 8px;
@@ -124,16 +144,17 @@
height: 120px; height: 120px;
float: left; float: left;
text-align: center; text-align: center;
text-decoration: none;
overflow: hidden; overflow: hidden;
border-radius: 5px; border-radius: 5px;
color: #555;
cursor: pointer; cursor: pointer;
border: 2px solid rgba(0,0,0,0); border: 2px solid rgba(0,0,0,0);
&:hover { &:hover, &.hover {
color: #e80; color: #e80;
border-color: #eee; border-color: #eee;
background-color: #f6f6f6; background-color: #f6f6f6;
//.box-shadow( 0, 0, 20px, #999 );
} }
.icon { .icon {
display: block; display: block;
@@ -155,6 +176,25 @@
display: none; display: none;
} }
} }
&.error {
a, a:active, a:visited {
color: #aaa;
text-decoration: none;
.label {
.hint {
padding: 0 6px;
font-size: 0.9em;
color: #c55;
}
}
&:hover, &.hover {
color: #e80;
border-color: #eee;
background-color: #f6f6f6;
}
}
}
} }
} }
} }

View File

@@ -1,26 +1,63 @@
#tree { #tree {
display: none;
position: fixed; position: fixed;
left: -200px;
display: none;
left: 0; left: 0;
top: 80px; top: 0;
overflow: auto;
font-size: 0.85em; font-size: 0.85em;
padding: 16px 32px 16px 16px; padding: 16px 32px 16px 16px;
background-color: rgb(240,240,240); background-color: rgb(241,241,241);
border: 1px solid rgb(225,225,225); border: 2px solid rgb(210,210,210);
border-left: none; border-left: none;
.border-radius ( 0 15px 15px 0 ); .border-radius ( 0 15px 15px 0 );
.box-shadow( 0 0 30px #999 );
.entry { .entry {
> a, > a.visited { .blank, .indicator {
display: inline-block;
width: 16px;
height: 25px;
float: left;
}
.indicator {
opacity: 0.7;
.transition( all 0.2s ease-in-out );
cursor: pointer;
&:hover {
opacity: 1;
}
img {
position: relative;
left: 0;
top: 3px;
width: 12px;
height: 12px;
vertical-align: bottom;
.transition( all 0.2s ease-in-out );
}
&.open {
img {
.transform( rotate(90deg) );
}
}
&.unknown {
opacity: 0.3;
}
}
> a, > a:active, > a.visited {
margin-left: 16px;
padding: 4px 6px; padding: 4px 6px;
border: 1px solid rgba(0,0,0,0); border: 1px solid rgba(0,0,0,0);
.border-radius( 5px ); .border-radius( 5px );
display: block; display: block;
color: #555;
text-decoration: none;
opacity: 0.7; opacity: 0.7;
&:hover { &:hover, &.hover {
color: #e80;
background-color: rgba(255,255,255,0.5); background-color: rgba(255,255,255,0.5);
opacity: 1; opacity: 1;
} }
@@ -39,7 +76,7 @@
.hint { .hint {
display: inline-block; display: inline-block;
margin-left: 12px; margin-left: 12px;
font-style: italic; font-size: 0.9em;
color: #ccc; color: #ccc;
img { img {
width: 10px; width: 10px;
@@ -47,26 +84,29 @@
vertical-align: baseline; vertical-align: baseline;
} }
} }
.error {
color: #c55;
}
} }
&.file { &.file {
display: none; display: none;
} }
&.current { &.current {
> a, > a:visited { > a, > a:active, > a:visited {
border: 1px solid rgba(0,0,0,0.1); border: 1px solid rgb(221,221,221);
background-color: rgba(255,255,255,0.5); background-color: rgba(255,255,255,0.5);
opacity: 1; opacity: 1;
} }
} }
&.notListable { &.error {
> a, > a:visited { > a, > a:active, > a:visited {
color: #999; color: #999;
&:hover, &.hover {
color: #e80;
} }
} }
ul { .hint {
color: #c55;
}
}
.content {
list-style: none; list-style: none;
margin-left: 20px; margin-left: 20px;
} }

View File

@@ -14,6 +14,7 @@ html.no-js {
} }
} }
body { body {
font-family: Ubuntu, sans-serif; font-family: Ubuntu, sans-serif;
font-size: 16px; font-size: 16px;
@@ -22,16 +23,6 @@ body {
} }
a, a:visited {
color: #555;
text-decoration: none;
&:hover {
color: #e80;
}
}
body > nav { body > nav {
position: fixed; position: fixed;
z-index: 1; z-index: 1;
@@ -39,9 +30,8 @@ body > nav {
left: 0; left: 0;
top: 0; top: 0;
font-size: 0.85em; font-size: 0.85em;
background-color: rgb(240,240,240); background-color: rgb(241,241,241);
border-bottom: 1px solid rgb(225,225,225); border-bottom: 2px solid rgb(210,210,210);
.box-shadow( 0 0 30px #555 );
span.jsDisabledFallback { span.jsDisabledFallback {
display: block; display: block;
@@ -50,14 +40,37 @@ body > nav {
padding: 0 10px; padding: 0 10px;
color: #999; color: #999;
} }
li { a, a:active, a:visited {
color: #555;
cursor: pointer; cursor: pointer;
text-decoration: none;
opacity: 0.7; opacity: 0.7;
.transition( all 0.2s ease-in-out ); .transition( all 0.2s ease-in-out );
&.crumb { display: block;
height: 30px;
line-height: 30px;
padding: 0 10px;
&:hover, &.hover {
color: #e80;
background-color: rgba(255,255,255,0.5);
opacity: 1.0;
}
}
.current a {
background-color: rgba(255,255,255,0.5);
opacity: 1.0;
}
img {
width: 16px;
height: 16px;
vertical-align: bottom;
padding: 0 6px 6px 0;
}
.crumb {
float: left; float: left;
border-right: 1px dotted rgb(225,225,225); border-right: 1px solid rgb(231,231,231);
.hint { .hint {
margin-left: 8px; margin-left: 8px;
font-style: italic; font-style: italic;
@@ -70,37 +83,15 @@ body > nav {
padding: 0px; padding: 0px;
} }
} }
&.current { .view {
background-color: rgba(255,255,255,0.5);
opacity: 1.0;
}
&.view {
float: right; float: right;
border-left: 1px dotted rgb(225,225,225); border-left: 1px solid rgb(231,231,231);
}
&:hover, &:hover a {
background-color: rgba(255,255,255,0.5);
color: #e80;
opacity: 1.0;
}
}
a {
display: block;
height: 30px;
line-height: 30px;
padding: 0 10px;
}
img {
width: 16px;
height: 16px;
vertical-align: bottom;
padding: 0 6px 6px 0;
} }
} }
#content { #content {
max-width: 980px; max-width: 960px;
margin: 0 auto; margin: 0 auto;
> header { > header {
@@ -130,15 +121,16 @@ body > footer {
left: 0; left: 0;
bottom: 0; bottom: 0;
padding: 10px 0; padding: 10px 0;
border-top: 1px solid rgb(225,225,225); background-color: rgb(241,241,241);
background-color: rgb(240,240,240); border-top: 2px solid rgb(210,210,210);
color: #999; color: #999;
font-size: 0.85em; font-size: 0.85em;
text-align: center; text-align: center;
.box-shadow( 0 0 30px #555 );
a, a:visited { a, a:active, a:visited {
color: #555; color: #555;
text-decoration: none;
.transition( all 0.2s ease-in-out ); .transition( all 0.2s ease-in-out );
&:hover { &:hover {
@@ -152,15 +144,14 @@ body > footer {
position: absolute; position: absolute;
left: 6px; left: 6px;
bottom: 6px; bottom: 6px;
float: left; opacity: 0.4;
.transition( all 0.2s ease-in-out );
img { img {
width: 20px; width: 20px;
height: 20px; height: 20px;
opacity: 0.4;
.transition( all 0.2s ease-in-out );
} }
&:hover img { &:hover {
opacity: 0.8; opacity: 0.8;
} }
} }

View File

@@ -11,12 +11,13 @@
<img class="techclass" src="/h5ai/images/html5-storage.png" alt="html5-storage" /> <img class="techclass" src="/h5ai/images/html5-storage.png" alt="html5-storage" />
<img class="techclass" src="/h5ai/images/html5-css3.png" alt="html5-css3" /> <img class="techclass" src="/h5ai/images/html5-css3.png" alt="html5-css3" />
</a> </a>
<a href="http://larsjung.de/h5ai" target="_blank" title="h5ai %BUILD_VERSION%">h5ai</a> <a href="http://larsjung.de/h5ai" target="_blank" title="h5ai %BUILD_VERSION%">h5ai %BUILD_VERSION%</a>
using <span class="l10n-footerUsing">using</span>
<a href="http://tiheum.deviantart.com/art/Faenza-Icons-173323228" target="_blank" title="icon theme for Gnome">Faenza icons</a> <a href="http://tiheum.deviantart.com/art/Faenza-Icons-173323228" target="_blank" title="icon theme for Gnome">Faenza icons</a>
</footer> </footer>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script>window.jQuery || document.write( '<script src="/h5ai/js/lib/jquery.min.js"><\/script>' )</script> <script>window.jQuery || document.write( '<script src="/h5ai/js/lib/jquery.min.js"><\/script>' )</script>
<script src="/h5ai/options.js"></script>
<script src="/h5ai/js/main.js"></script> <script src="/h5ai/js/main.js"></script>
</body> </body>
</html> </html>

View File

@@ -13,14 +13,16 @@
<script src="/h5ai/js/lib/modernizr.min.js"></script> <script src="/h5ai/js/lib/modernizr.min.js"></script>
</head> </head>
<body> <body>
<nav> <nav class="clearfix">
<span class="jsDisabledFallback">Directory index · JavaScript is disabled</span> <span class="jsDisabledFallback">Directory index · JavaScript is disabled</span>
<ul> <ul>
<li id="domain" class="crumb"><a href="/"><img src="/h5ai/images/home.png" alt="domain" /><span>domain</span></a></li> <li id="viewicons" class="view">
<li id="viewicons" class="view"><a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" />icons</a></li> <a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" /><span class="l10n-viewIcons">icons</span></a>
<li id="viewdetails" class="view" ><a href="#"><img src="/h5ai/images/view-details.png" alt="view-details" />details</a></li> </li>
<li id="viewdetails" class="view" >
<a href="#"><img src="/h5ai/images/view-details.png" alt="view-details" /><span class="l10n-viewDetails">details</span></a>
</li>
</ul> </ul>
<div class="clearfix"></div>
</nav> </nav>
<section id="content"> <section id="content">
<header></header> <header></header>

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

View File

Before

Width:  |  Height:  |  Size: 441 B

After

Width:  |  Height:  |  Size: 441 B

View File

Before

Width:  |  Height:  |  Size: 587 B

After

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 B

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
src/h5ai/images/blank.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 697 B

BIN
src/h5ai/images/tree.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

View File

@@ -1,43 +1,32 @@
( function( $ ) {
var H5ai = function ( options, langs, pathCache ) {
/*******************************
* init after dom load
*******************************/
$( function() {
$.h5ai = new H5ai();
} );
H5ai = function ( options ) {
/******************************* /*******************************
* config * config
*******************************/ *******************************/
var config = { var defaults = {
columnClasses: [ "icon", "name", "date", "size" ],
defaultSortOrder: "C=N;O=A", defaultSortOrder: "C=N;O=A",
viewmodes: [ "details", "icons" ],
store: { store: {
viewmode: "h5ai.viewmode" viewmode: "h5ai.viewmode"
}, },
icons: {
crumb: "/h5ai/images/crumb.png",
ascending: "/h5ai/images/ascending.png",
descending: "/h5ai/images/descending.png"
},
customHeader: "h5ai.header.html", customHeader: "h5ai.header.html",
customFooter: "h5ai.footer.html", customFooter: "h5ai.footer.html",
callbacks: { callbacks: {
folderClick: [], pathClick: []
fileClick: [] },
}
viewmodes: [ "details", "icons" ],
showTree: false,
folderStatus: {
},
lang: undefined,
useBrowserLang: true,
setParentFolderLabels: true,
linkHoverStates: true
}; };
this.config = $.extend( {}, defaults, options );
@@ -45,19 +34,10 @@
* public api * public api
*******************************/ *******************************/
this.folderClick = function ( fn ) { this.pathClick = function ( fn ) {
if ( typeof fn === "function" ) { if ( $.isFunction( fn ) ) {
config.callbacks.folderClick.push( fn ); this.config.callbacks.pathClick.push( fn );
};
return this;
};
this.fileClick = function ( fn ) {
if ( typeof fn === "function" ) {
config.callbacks.fileClick.push( fn );
}; };
return this; return this;
}; };
@@ -65,15 +45,19 @@
/******************************* /*******************************
* init (will be called at the bottom) * init
*******************************/ *******************************/
var init = function () { this.init = function () {
applyViewmode(); document.title = document.domain + decodeURI( document.location.pathname );
initBreadcrumb();
initViews(); this.applyViewmode();
customize(); this.initBreadcrumb();
this.initTopSpace();
this.initViews();
this.customize();
this.localize( langs, this.config.lang, this.config.useBrowserLang );
}; };
@@ -82,18 +66,10 @@
* callback triggers * callback triggers
*******************************/ *******************************/
var triggerFolderClick = function ( label ) { this.triggerPathClick = function ( path, context ) {
for ( idx in config.callbacks.folderClick ) { for ( idx in this.config.callbacks.pathClick ) {
config.callbacks.folderClick[idx].call( window, label ); this.config.callbacks.pathClick[idx].call( window, path, context );
};
};
var triggerFileClick = function ( label ) {
for ( idx in config.callbacks.fileClick ) {
config.callbacks.fileClick[idx].call( window, label );
}; };
}; };
@@ -103,55 +79,99 @@
* local stored viewmode * local stored viewmode
*******************************/ *******************************/
var getViewmode = function () { this.getViewmode = function () {
var viewmode = localStorage.getItem( config.store.viewmode ); var viewmode = localStorage.getItem( this.config.store.viewmode );
if ( $.inArray( viewmode, config.viewmodes ) ) { return $.inArray( viewmode, this.config.viewmodes ) >= 0 ? viewmode : this.config.viewmodes[0];
return viewmode;
};
return config.viewmodes[0];
}; };
var applyViewmode = function ( viewmode ) { this.applyViewmode = function ( viewmode ) {
$( "#table" ).hide();
if ( viewmode !== undefined ) { if ( viewmode !== undefined ) {
localStorage.setItem( config.store.viewmode, viewmode ); localStorage.setItem( this.config.store.viewmode, viewmode );
}; };
$( "body > nav li.view" ).removeClass( "current" ); viewmode = this.getViewmode();
if ( getViewmode() === "icons" ) {
$( "body > nav li.view" ).hide().removeClass( "current" );
if ( this.config.viewmodes.length > 1 ) {
if ( $.inArray( "details", this.config.viewmodes ) >= 0 ) {
$( "#viewdetails" ).show();
};
if ( $.inArray( "icons", this.config.viewmodes ) >= 0 ) {
$( "#viewicons" ).show();
};
};
if ( viewmode === "details" ) {
$( "#viewdetails" ).closest( "li" ).addClass( "current" );
$( "#table" ).hide();
$( "#extended" ).addClass( "details-view" ).removeClass( "icons-view" ).show();
} else if ( viewmode === "icons" ) {
$( "#viewicons" ).closest( "li" ).addClass( "current" ); $( "#viewicons" ).closest( "li" ).addClass( "current" );
$( "#table" ).hide();
$( "#extended" ).removeClass( "details-view" ).addClass( "icons-view" ).show(); $( "#extended" ).removeClass( "details-view" ).addClass( "icons-view" ).show();
} else { } else {
$( "#viewdetails" ).closest( "li" ).addClass( "current" ); $( "#table" ).show();
$( "#extended" ).addClass( "details-view" ).removeClass( "icons-view" ).show(); $( "#extended" ).hide();
}; };
}; };
/******************************* /*******************************
* breadcrumb and doc title * breadcrumb
*******************************/ *******************************/
var initBreadcrumb = function () { this.initBreadcrumb = function () {
$( "#domain span" ).text( document.domain ); var $ul = $( "body > nav ul" );
var pathname = decodeURI( document.location.pathname );
var parts = pathname.split( "/" ); var pathname = "/";
var path = "/"; var path = pathCache.getPathForFolder( pathname );
var $ul = $( "nav ul" ); $ul.append( path.updateCrumbHtml() );
for ( idx in parts ) {
var part = parts[idx]; var pathnameParts = decodeURI( document.location.pathname ).split( "/" );
for ( idx in pathnameParts ) {
var part = pathnameParts[idx];
if ( part !== "" ) { if ( part !== "" ) {
path += part + "/"; pathname += part + "/";
$ul.append( $( "<li class='crumb'><a href='" + path + "'><img src='" + config.icons.crumb + "' alt='>' />" + part + "</a></li>" ) ); var path = pathCache.getPathForFolder( pathname );
$ul.append( path.updateCrumbHtml() );
};
}; };
}; };
$( "body > nav .crumb:last" ).addClass( "current" );
document.title = document.domain + pathname;
/*******************************
* top space, depending on nav height
*******************************/
this.initTopSpace = function () {
function adjustTopSpace() {
var winHeight = $( window ).height();
var navHeight = $( "body > nav" ).outerHeight();
var footerHeight = $( "body > footer" ).outerHeight();
var contentSpacing = 50;
var treeSpacing = 50;
$( "body" )
.css( "margin-top", "" + ( navHeight + contentSpacing ) + "px" )
.css( "margin-bottom", "" + ( footerHeight + contentSpacing ) + "px" );
$( "#tree" )
.css( "top", "" + ( navHeight + treeSpacing ) + "px" )
.css( "max-height", "" + ( winHeight - navHeight - footerHeight - 36 - 2 * treeSpacing ) + "px" );
};
$( window ).resize( function () {
adjustTopSpace();
} );
adjustTopSpace();
}; };
@@ -160,23 +180,9 @@
* table view * table view
*******************************/ *******************************/
var initTableView = function () { this.initTableView = function () {
function getColumnClass( idx ) {
if ( idx >= 0 && idx < config.columnClasses.length ) {
return config.columnClasses[idx];
};
return "unknown";
};
$( "#table td" ).removeAttr( "align" ).removeAttr( "valign" ); $( "#table td" ).removeAttr( "align" ).removeAttr( "valign" );
$( "#table tr" ).each( function () {
var colIdx = 0;
$( this ).find( "th,td" ).each( function () {
$( this ).addClass( getColumnClass( colIdx++ ) );
} );
} );
}; };
@@ -185,30 +191,31 @@
* extended view * extended view
*******************************/ *******************************/
var initExtendedView = function () { this.initExtendedView = function () {
var $ul = $( "<ul/>" ); var $ul = $( "<ul/>" );
// headers // headers
var $ths = $( "#table th" );
var $label = $ths.eq( 1 ).find( "a" );
var $date = $ths.eq( 2 ).find( "a" );
var $size = $ths.eq( 3 ).find( "a" );
var $li = $( "<li class='header' />" ).appendTo( $ul ); var $li = $( "<li class='header' />" ).appendTo( $ul );
$( "<a class='icon'></a>" ).appendTo( $li ); $( "<a class='icon'></a>" ).appendTo( $li );
var $label = $( "th.name a" ); $( "<a class='label' href='" + $label.attr( "href" ) + "'><span class='l10n-columnName'>" + $label.text() + "</span></a>" ).appendTo( $li );
var $date = $( "th.date a" ); $( "<a class='date' href='" + $date.attr( "href" ) + "'><span class='l10n-columnLastModified'>" + $date.text() + "</span></a>" ).appendTo( $li );
var $size = $( "th.size a" ); $( "<a class='size' href='" + $size.attr( "href" ) + "'><span class='l10n-columnSize'>" + $size.text() + "</span></a>" ).appendTo( $li );
$( "<a class='label' href='" + $label.attr( "href" ) + "'>" + $label.text() + "</a>" ).appendTo( $li );
$( "<a class='date' href='" + $date.attr( "href" ) + "'>" + $date.text() + "</a>" ).appendTo( $li );
$( "<a class='size' href='" + $size.attr( "href" ) + "'>" + $size.text() + "</a>" ).appendTo( $li );
// header sort icons // header sort icons
var order = document.location.search; var order = document.location.search;
if ( order === "" ) { if ( order === "" ) {
order = config.defaultSortOrder; order = this.config.defaultSortOrder;
}; };
var $icon; var $icon;
if ( order.indexOf( "O=A" ) >= 0 ) { if ( order.indexOf( "O=A" ) >= 0 ) {
$icon = $( "<img src='" + config.icons.ascending + "' class='sort' alt='ascending' />" ); $icon = $( "<img src='/h5ai/images/ascending.png' class='sort' alt='ascending' />" );
} else { } else {
$icon = $( "<img src='" + config.icons.descending + "' class='sort' alt='descending' />" ); $icon = $( "<img src='/h5ai/images/descending.png' class='sort' alt='descending' />" );
}; };
if ( order.indexOf( "C=N" ) >= 0 ) { if ( order.indexOf( "C=N" ) >= 0 ) {
$li.find( "a.label" ).append( $icon ); $li.find( "a.label" ).append( $icon );
@@ -219,72 +226,41 @@
}; };
// entries // entries
$( "#table td.name a" ).closest( "tr" ).each( function () { $( "#table td" ).closest( "tr" ).each( function () {
var $tr = $( this ); var path = pathCache.getPathForTableRow( decodeURI( document.location.pathname ), this );
var $img = $tr.find( "td.icon img" ); $ul.append( path.updateExtendedHtml() );
var iconsmall = $img.attr( "src" );
var iconbig = iconsmall.replace( "16x16", "48x48" );
var alt = $img.attr( "alt" );
var $link = $tr.find( "td.name a" );
var label = $link.text();
var href = $link.attr( "href" );
var date = $tr.find( "td.date" ).text();
var size = $tr.find( "td.size" ).text();
var $li = $( "<li class='entry' />" ).appendTo( $ul );
if ( alt === "[DIR]" ) {
$li.addClass( "folder" );
} else {
$li.addClass( "file" );
}
var $a = $( "<a href='" + href + "' />" ).appendTo( $li );
$( "<span class='icon small'><img src='" + iconsmall + "' alt='" + alt + "' /></span>" ).appendTo( $a );
$( "<span class='icon big'><img src='" + iconbig + "' alt='" + alt + "' /></span>" ).appendTo( $a );
$( "<span class='label'>" + label + "</span>" ).appendTo( $a );
$( "<span class='date'>" + date + "</span>" ).appendTo( $a );
$( "<span class='size'>" + size + "</span>" ).appendTo( $a );
} ); } );
$( "#extended" ).append( $ul ); $( "#extended" ).append( $ul );
// empty // empty
$entries = $( "#extended .entry" ); if ( $ul.children( ".entry:not(.parentfolder)" ).size() === 0 ) {
if ( $entries.size() === 0 || $entries.size() === 1 && $entries.find( ".label" ).text() === "Parent Directory" ) {
$( "#extended" ).append( $( "<div class='empty'>empty</div>" ) ); $( "#extended" ).append( $( "<div class='empty'>empty</div>" ) );
}; };
// in case of floats // in case of floats
$( "#extended" ).append( $( "<div class='clearfix' />" ) ); $( "#extended" ).addClass( "clearfix" );
// click callbacks
$( "#extended .entry.folder" )
.click( function() {
triggerFolderClick( $( this ).find( ".label" ).text() );
} );
$( "#extended .entry.file" )
.click( function() {
triggerFileClick( $( this ).find( ".label" ).text() );
} );
}; };
/******************************* /*******************************
* init views * init views
*******************************/ *******************************/
var initViews = function () { this.initViews = function () {
initTableView(); this.initTableView();
initExtendedView(); this.initExtendedView();
$( "#viewdetails" ).closest( "li" ) $( "#viewdetails" ).closest( "li" )
.click( function () { .click( $.proxy( function () {
applyViewmode( "details" ); this.applyViewmode( "details" );
} ); }, this ) );
$( "#viewicons" ).closest( "li" ) $( "#viewicons" ).closest( "li" )
.click( function () { .click( $.proxy( function () {
applyViewmode( "icons" ); this.applyViewmode( "icons" );
} ); }, this ) );
}; };
@@ -293,10 +269,10 @@
* customize * customize
*******************************/ *******************************/
var customize = function () { this.customize = function () {
$.ajax( { $.ajax( {
url: config.customHeader, url: this.config.customHeader,
dataType: "html", dataType: "html",
success: function ( data ) { success: function ( data ) {
$( "#content > header" ).append( $( data ) ).show(); $( "#content > header" ).append( $( data ) ).show();
@@ -304,7 +280,7 @@
} ); } );
$.ajax( { $.ajax( {
url: config.customFooter, url: this.config.customFooter,
dataType: "html", dataType: "html",
success: function ( data ) { success: function ( data ) {
$( "#content > footer" ).prepend( $( data ) ).show(); $( "#content > footer" ).prepend( $( data ) ).show();
@@ -315,10 +291,28 @@
/******************************* /*******************************
* finally run init * localization
*******************************/ *******************************/
init(); this.localize = function ( data, lang, useBrowserLang ) {
if ( useBrowserLang === true ) {
var browserLang = navigator.language;
if ( data[ browserLang ] !== undefined ) {
lang = browserLang;
} else if ( browserLang.length > 2 && data[ browserLang.substr( 0, 2 ) ] !== undefined ) {
lang = browserLang.substr( 0, 2 );
};
if ( lang === "en" ) {
lang = undefined;
};
}; };
} )( jQuery ); if ( data[ lang ] !== undefined ) {
var selected = data[ lang ];
for ( key in selected ) {
$( ".l10n-" + key ).text( selected[key] );
};
};
};
};

View File

@@ -1,312 +0,0 @@
( function( $ ) {
/*******************************
* init after dom load
*******************************/
$( function() {
window.setTimeout( function() {
$.h5aiTree = new H5aiTree();
}, 1 );
} );
H5aiTree = function ( options ) {
var folderRegEx = /\/$/;
var pathnameRegEx = /^(\/(.*\/)*)([^\/]+\/?)$/;
var contentTypeRegEx = /^text\/html;h5ai=/;
function init() {
checkCrumb();
initShifting();
populateTree();
};
function splitPathname( pathname ) {
if ( pathname === "/" ) {
return [ "", "/" ];
};
var match = pathnameRegEx.exec( pathname );
return [ match[1], match[3] ];
};
function checkCrumb() {
$( "li.crumb a" ).each( function() {
var $a = $( this );
var pathname = $a.attr( "href" );
checkPathname( pathname, function ( status ) {
if ( status !== 0 ) {
$( "<img class='hint' src='/h5ai/images/page.png' alt='not listable' />" ).appendTo( $a );
if ( status !== 200 ) {
$( "<span class='hint'>(" + status + ")</span>" ).appendTo( $a );
};
};
} );
} );
};
function shiftTree( show ) {
var $tree = $( "#tree" );
var $extended = $( "#extended" );
var show = show || false;
if ( $tree.outerWidth() < $extended.offset().left || show ) {
$tree.stop().animate( { left: 0 } );
} else {
//var left = Math.max( 24 - $tree.outerWidth(), $extended.offset().left - $tree.outerWidth() - 16 );
var left = 24 - $tree.outerWidth();
$tree.stop().animate( { left: left } );
};
};
function initShifting() {
$( "#tree" ).hover(
function () {
shiftTree( true );
},
function () {
shiftTree();
}
);
$( window ).resize( function() {
shiftTree();
} );
};
function populateTree() {
var $tree = $( "#tree" );
$tree.css( { left: -400 } ).show();
shiftTree();
var pathname = decodeURI( document.location.pathname );
fetchTree( pathname, function( entry ) {
$tree.empty().append( entry.toHtml() );
shiftTree();
} );
};
function fetchTree( pathname, callback ) {
walkBack( pathname, function( walkbackedPathname ) {
var entry = new Entry( walkbackedPathname );
fetchEntriesRecursive( walkbackedPathname, function ( content ) {
entry.content = content;
callback( entry );
} );
} );
};
function walkBack( pathname, callback ) {
var splits = splitPathname( pathname );
var parent = splits[0];
if ( parent === "" ) {
callback( pathname );
} else {
checkPathname( parent, function( state ) {
if ( state === 0 ) {
walkBack( parent, callback );
} else {
callback( pathname );
};
} );
};
};
function fetchEntriesRecursive( pathname, callback ) {
fetchEntries( pathname, false, function ( entries ) {
if ( entries instanceof Array ) {
for ( idx in entries ) {
( function ( entry ) {
if ( entry.isFolder ) {
fetchEntriesRecursive( entry.absHref, function( content ) {
entry.content = content;
callback( entries );
} );
};
} ) ( entries[idx] );
};
};
callback( entries );
} );
};
function fetchEntries( pathname, includeParent, callback ) {
checkPathname( pathname, function ( status ) {
console.log( "checkPathname", pathname, status );
if ( status !== 0 ) {
callback( status );
} else {
$.ajax( {
url: pathname,
type: "GET",
dataType: "html",
error: function ( xhr ) {
// since it was checked before this should never happen
callback( xhr.status );
},
success: function ( html, status, xhr ) {
if ( !contentTypeRegEx.test( xhr.getResponseHeader( "Content-Type" ) ) ) {
// since it was checked before this should never happen
callback( xhr.status );
} else {
var entries = [];
$( html ).find( "#table table td" ).closest( "tr" ).each( function () {
var entry = new Entry( pathname, this );
if ( !entry.isParentFolder || includeParent ) {
entries.push( entry );
};
} );
callback( entries );
};
}
} );
};
} );
};
function checkPathname( pathname, callback ) {
$.ajax( {
url: pathname,
type: "HEAD",
complete: function ( xhr ) {
if ( xhr.status === 200 && contentTypeRegEx.test( xhr.getResponseHeader( "Content-Type" ) ) ) {
callback( 0 );
} else {
callback( xhr.status );
};
}
} );
};
Entry = function ( folder, tableRow ) {
if ( !folderRegEx.test( folder ) ) {
folder += "/";
};
if ( tableRow !== undefined ) {
var $tds = $( tableRow ).find( "td" );
var $img = $( $tds.get( 0 ) ).find( "img" );
var $a= $( $tds.get( 1 ) ).find( "a" );
this.parentFolder = folder;
this.icon16 = $img.attr( "src" );
this.alt = $img.attr( "alt" );
this.label = $a.text();
this.href = $a.attr("href");
this.date = $( $tds.get(2) ).text();
this.size = $( $tds.get(3) ).text();
} else {
var splits = splitPathname( folder );
this.parentFolder = splits[0];
this.label = splits[1];
this.icon16 = "/h5ai/icons/16x16/folder.png";
this.alt = "[DIR]";
this.href = this.label;
this.date = "";
this.size = "";
if ( this.label === "/" ) {
this.label = document.domain + "/";
};
};
this.icon48 = this.icon16.replace( "16x16", "48x48" );
this.isFolder = ( this.alt === "[DIR]" );
this.isParentFolder = ( this.isFolder && this.label === "Parent Directory" );
this.absHref = this.isParentFolder ? this.href : this.parentFolder + this.href;
this.content = undefined;
this.isComplete = function () {
if ( this.isFolder ) {
if ( this.content === undefined ) {
return false;
} else if ( this.content instanceof Array ) {
for ( idx in this.content ) {
if ( !this.content[idx].isComplete() ) {
return false;
};
};
};
};
return true;
};
this.toHtml = function () {
var $entry = $( "<div class='entry' />" );
try {
var $a = $( "<a href='" + this.absHref + "' />" )
.appendTo( $entry )
.append( $( "<span class='icon'><img src='" + this.icon16 + "' /></span>" ) )
.append( $( "<span class='label'>" + this.label + "</span>" ) );
if ( this.isFolder ) {
$entry.addClass( "folder" );
if ( this.absHref === document.location.pathname ) {
$a.find( ".icon img" ).attr( "src", "/h5ai/images/folder-open.png" );
$entry.addClass( "current" );
};
if ( this.content instanceof Array ) {
var $ul = $( "<ul class='content' />" ).appendTo( $entry );
for ( idx in this.content ) {
$( "<li />" ).append( this.content[idx].toHtml() ).appendTo( $ul );
};
} else if ( this.content === undefined ) {
$a.append( $( "<span class='hint'><img src='/h5ai/images/loading.png' /></span>" ) );
} else if ( this.content === 200 ) {
$a.find( ".icon img" ).attr( "src", "/h5ai/images/folder-page.png" );
$a.append( $( "<span class='hint'><img src='/h5ai/images/page.png' /></span>" ) );
} else {
$a.append( $( "<span class='hint error'>" + this.content + "</span>" ) );
$entry.addClass( "notListable" );
};
} else {
$entry.addClass( "file" );
};
} catch( err ) {
$( "<span class='fail'>fail</span>" ).appendTo( $entry );
};
return $entry;
};
};
init()
};
} )( jQuery );

403
src/h5ai/js/inc/path.js Normal file
View File

@@ -0,0 +1,403 @@
var PathCache = function () {
var pathnameRegEx = /^(\/(.*\/)*)([^\/]+\/?)$/;
this.splitPathname = function ( pathname ) {
if ( pathname === "/" ) {
return [ "", "/" ];
};
var match = pathnameRegEx.exec( pathname );
return [ match[1], match[3] ];
};
this.cache = {};
this.loadCache = function () {
var json = localStorage.getItem( "h5ai.cache" );
var objs = $.evalJSON( json );
var cache = {};
for ( idx in objs ) {
var obj = objs[idx];
var path = this.objectToPath( obj );
cache[path.absHref] = path;
};
console.log( "loaded: ", cache );
return cache;
};
this.storeCache = function () {
var objs = [];
for ( ref in this.cache ) {
var path = this.cache[ref];
if ( path.isFolder ) {
objs.push( this.pathToObject( path ) );
};
};
var json = $.toJSON( objs );
localStorage.setItem( "h5ai.cache", json );
};
this.pathToObject = function ( path ) {
var object = {
r: path.absHref,
s: path.status,
c: [],
o: path.treeOpen
};
if ( path.content !== undefined ) {
for ( ref in path.content ) {
object.c.push( ref );
};
};
return object;
};
this.objectToPath = function ( obj ) {
var path = this.getPathForFolder( obj.r );
path.status = obj.s;
path.content = {};
path.treeOpen = obj.o;
for ( idx in obj.c ) {
var href = obj.c[idx];
path.content[href] = this.getPathForFolder( href );
};
return path;
};
this.getPathForFolder = function ( folder ) {
return this.getCachedPath( new Path( this, folder ) );
};
this.getPathForTableRow = function ( parentFolder, tableRow ) {
return this.getCachedPath( new Path( this, parentFolder, tableRow ) );
};
this.getCachedPath = function ( path ) {
if ( path.isParentFolder ) {
return path;
};
var cachedPath = this.cache[path.absHref];
if ( cachedPath !== undefined ) {
return cachedPath;
};
this.cache[path.absHref] = path;
this.storeCache();
return path;
};
this.cache = this.loadCache();
};
var Path = function ( pathCache, folder, tableRow ) {
if ( ! /\/$/.test( folder ) ) {
folder += "/";
};
if ( tableRow !== undefined ) {
var $tds = $( tableRow ).find( "td" );
var $img = $tds.eq( 0 ).find( "img" );
var $a= $tds.eq( 1 ).find( "a" );
this.parentFolder = folder;
this.icon16 = $img.attr( "src" );
this.alt = $img.attr( "alt" );
this.label = $a.text();
this.href = decodeURI( $a.attr("href") );
this.date = $tds.eq( 2 ).text();
this.size = $tds.eq( 3 ).text();
} else {
var splits = pathCache.splitPathname( folder );
this.parentFolder = splits[0];
this.label = splits[1];
this.icon16 = "/h5ai/icons/16x16/folder.png";
this.alt = "[DIR]";
this.href = this.label;
this.date = "";
this.size = "";
if ( this.label === "/" ) {
this.label = document.domain + "/";
};
};
if ( /\/$/.test( this.label ) ) {
this.label = this.label.slice( 0, -1 );
};
this.icon48 = this.icon16.replace( "16x16", "48x48" );
this.isFolder = ( this.alt === "[DIR]" );
this.isParentFolder = ( this.isFolder && this.label === "Parent Directory" );
this.absHref = this.isParentFolder ? this.href : this.parentFolder + this.href;
this.isCurrentFolder = ( this.absHref === decodeURI( document.location.pathname ) );
this.isDomain = ( this.absHref === "/" );
if ( this.isParentFolder && h5ai.config.setParentFolderLabels ) {
if ( this.isDomain ) {
this.label = decodeURI( document.domain );
} else {
this.label = pathCache.splitPathname( pathCache.splitPathname( this.parentFolder )[0] )[1].slice( 0, -1 );
};
};
this.status = undefined; // undefined, "h5ai" or HTTP response code
this.content = undefined; // associative array path.absHref -> path
this.html = {
$crumb: undefined,
$extended: undefined,
$tree: undefined
};
this.treeOpen = false;
this.isEmpty = function() {
return this.content === undefined || $.isEmptyObject( this.content );
};
this.onClick = function ( context ) {
pathCache.storeCache();
h5ai.triggerPathClick( this, context );
};
this.onHoverIn = function () {
if ( h5ai.config.linkHoverStates ) {
for ( ref in this.html ) {
$ref = this.html[ref];
if ( $ref !== undefined ) {
$ref.find( "> a" ).addClass( "hover" );
};
};
};
};
this.onHoverOut = function () {
if ( h5ai.config.linkHoverStates ) {
for ( ref in this.html ) {
$ref = this.html[ref];
if ( $ref !== undefined ) {
$ref.find( "> a" ).removeClass( "hover" );
};
};
};
};
this.updateHtml = function () {
this.updateCrumbHtml();
this.updateExtendedHtml();
this.updateTreeHtml();
};
this.updateCrumbHtml = function () {
var $html = $( "<li class='crumb' />" ).data( "path", this );
try {
$html.addClass( this.isFolder ? "folder" : "file" );
var $a = $( "<a href='" + this.absHref + "'><img src='/h5ai/images/crumb.png' alt='>' />" + this.label + "</a>" );
$a.click( $.proxy( function() { this.onClick( "crumb" ); }, this ) );
$a.hover( $.proxy( function() { this.onHoverIn( "crumb" ); }, this ), $.proxy( function() { this.onHoverOut( "crumb" ); }, this ) );
$html.append( $a );
if ( this.isDomain ) {
$html.addClass( "domain" );
$a.find( "img" ).attr( "src", "/h5ai/images/home.png" );
};
if ( this.isCurrentFolder ) {
$html.addClass( "current" );
};
if ( !isNaN( this.status ) ) {
if ( this.status === 200 ) {
$( "<img class='hint' src='/h5ai/images/page.png' alt='not listable' />" ).appendTo( $a );
} else {
$( "<span class='hint'>(" + this.status + ")</span>" ).appendTo( $a );
};
};
} catch( err ) {
console.log( "updateCrumbHtml failed", err );
$( "<span class='fail'>failed</span>" ).appendTo( $html );
};
if ( this.html.$crumb !== undefined ) {
this.html.$crumb.replaceWith( $html );
};
this.html.$crumb = $html;
return $html;
};
this.updateExtendedHtml = function () {
var $html = $( "<li class='entry' />" ).data( "path", this );
try {
$html.addClass( this.isFolder ? "folder" : "file" );
var $a = $( "<a href='" + this.href + "' />" ).appendTo( $html );
$a.click( $.proxy( function() { this.onClick( "extended" ); }, this ) );
$a.hover( $.proxy( function() { this.onHoverIn( "extended" ); }, this ), $.proxy( function() { this.onHoverOut( "extended" ); }, this ) );
$( "<span class='icon small'><img src='" + this.icon16 + "' alt='" + this.alt + "' /></span>" ).appendTo( $a );
$( "<span class='icon big'><img src='" + this.icon48 + "' alt='" + this.alt + "' /></span>" ).appendTo( $a );
var $label = $( "<span class='label'>" + this.label + "</span>" ).appendTo( $a );
$( "<span class='date'>" + this.date + "</span>" ).appendTo( $a );
$( "<span class='size'>" + this.size + "</span>" ).appendTo( $a );
if ( this.isParentFolder ) {
if ( !h5ai.config.setParentFolderLabels ) {
$label.addClass( "l10n-parentDirectory" );
};
$html.addClass( "parentfolder" );
};
if ( !isNaN( this.status ) ) {
if ( this.status === 200 ) {
$html.addClass( "page" );
$a.find( ".icon.small img" ).attr( "src", "/h5ai/icons/16x16/folder-page.png" );
$a.find( ".icon.big img" ).attr( "src", "/h5ai/icons/48x48/folder-page.png" );
} else {
$html.addClass( "error" );
$label.append( $( "<span class='hint'> " + this.status + " </span>" ) );
};
};
} catch( err ) {
console.log( "updateExtendedHtml failed", err );
$( "<span class='fail'>failed</span>" ).appendTo( $html );
};
if ( this.html.$extended !== undefined ) {
this.html.$extended.replaceWith( $html );
};
this.html.$extended = $html;
return $html;
};
this.updateTreeHtml = function () {
var $html = $( "<div class='entry' />" ).data( "path", this );
var $blank = $( "<span class='blank' />" ).appendTo( $html );
try {
$html.addClass( this.isFolder ? "folder" : "file" );
var $a = $( "<a href='" + this.absHref + "' />" )
.appendTo( $html )
.append( $( "<span class='icon'><img src='" + this.icon16 + "' /></span>" ) )
.append( $( "<span class='label'>" + this.label + "</span>" ) );
$a.click( $.proxy( function() { this.onClick( "tree" ); }, this ) );
$a.hover( $.proxy( function() { this.onHoverIn( "tree" ); }, this ), $.proxy( function() { this.onHoverOut( "tree" ); }, this ) );
if ( this.isFolder ) {
// indicator
if ( this.status === undefined || !this.isEmpty() ) {
var $indicator = $( "<span class='indicator'><img src='/h5ai/images/tree.png' /></span>" );
if ( this.status === undefined ) {
$indicator.addClass( "unknown" );
} else if ( this.treeOpen ) {
$indicator.addClass( "open" );
};
$indicator.click( $.proxy( function( event ) {
if ( $indicator.hasClass( "unknown" ) ) {
tree.fetchStatusAndContent( this.absHref, false, $.proxy( function ( status, content ) {
this.status = status;
this.content = content;
this.treeOpen = true;
this.updateTreeHtml();
}, this ) );
} else if ( $indicator.hasClass( "open" ) ) {
this.treeOpen = false;
$indicator.removeClass( "open" );
$html.find( "> ul.content" ).slideUp();
} else {
this.treeOpen = true;
$indicator.addClass( "open" );
$html.find( "> ul.content" ).slideDown();
};
}, this ) );
$blank.replaceWith( $indicator );
};
// is this the domain?
if ( this.isDomain ) {
$html.addClass( "domain" );
$a.find( ".icon img" ).attr( "src", "/h5ai/icons/16x16/folder-home.png" );
};
// is this the current folder?
if ( this.isCurrentFolder ) {
$html.addClass( "current" );
$a.find( ".icon img" ).attr( "src", "/h5ai/icons/16x16/folder-open.png" );
};
// does it have subfolders?
if ( !this.isEmpty() ) {
var $ul = $( "<ul class='content' />" ).appendTo( $html );
for ( idx in this.content ) {
$( "<li />" ).append( this.content[idx].updateTreeHtml() ).appendTo( $ul );
};
if ( this.status === undefined || !this.treeOpen ) {
$ul.hide();
};
};
// reflect folder status
if ( !isNaN( this.status ) ) {
if ( this.status === 200 ) {
$a.find( ".icon img" ).attr( "src", "/h5ai/icons/16x16/folder-page.png" );
$a.append( $( "<span class='hint'><img src='/h5ai/images/page.png' /></span>" ) );
} else {
$html.addClass( "error" );
$a.append( $( "<span class='hint'>" + this.status + "</span>" ) );
};
};
};
} catch( err ) {
console.log( "updateTreeHtml failed", err );
$( "<span class='fail'>failed</span>" ).appendTo( $html );
};
if ( this.html.$tree !== undefined ) {
this.html.$tree.replaceWith( $html );
};
this.html.$tree = $html;
return $html;
};
};

154
src/h5ai/js/inc/tree.js Normal file
View File

@@ -0,0 +1,154 @@
var Tree = function ( pathCache, h5ai ) {
var THIS = this;
var contentTypeRegEx = /^text\/html;h5ai=/;
this.init = function () {
if ( h5ai.config.showTree ) {
this.updatePaths();
this.populateTree();
};
};
this.updatePath = function ( path ) {
if ( path.isFolder && !path.isParentFolder && path.status === undefined ) {
this.fetchStatus( path.absHref, function ( status ) {
if ( status !== "h5ai" ) {
path.status = status;
};
path.updateHtml();
} );
};
};
this.updatePaths = function () {
for ( var ref in pathCache.cache ) {
this.updatePath( pathCache.cache[ref] );
};
};
this.populateTree = function () {
var $tree = $( "#tree" );
var $extended = $( "#extended" );
var shiftTree = function ( show ) {
if ( $tree.outerWidth() < $extended.offset().left || show === true ) {
$tree.stop().animate( { left: 0 } );
} else {
$tree.stop().animate( { left: 18 - $tree.outerWidth() } );
};
};
$tree.hover( function () { shiftTree( true ); }, function () { shiftTree(); } );
$( window ).resize( function() {
shiftTree();
} );
this.fetchTree( decodeURI( document.location.pathname ), function( path ) {
$tree.append( path.updateTreeHtml() ).show();
shiftTree();
} );
};
this.fetchTree = function ( pathname, callback, childPath ) {
this.fetchPath( pathname, $.proxy( function ( path ) {
path.treeOpen = true;
if ( childPath !== undefined ) {
path.content[ childPath.absHref ] = childPath;
};
var parent = pathCache.splitPathname( pathname )[0];
if ( parent === "" ) {
callback( path );
} else {
this.fetchTree( parent, callback, path );
};
}, this ) );
};
this.fetchPath = function ( pathname, callback ) {
this.fetchStatusAndContent( pathname, false, function ( status, content ) {
var path = pathCache.getPathForFolder( pathname );
path.status = status;
path.content = content;
callback( path );
} );
};
this.fetchStatusAndContent = function ( pathname, includeParent, callback ) {
this.fetchStatus( pathname, function ( status ) {
if ( status !== "h5ai" ) {
callback( status, {} );
return;
};
$.ajax( {
url: pathname,
type: "GET",
dataType: "html",
error: function ( xhr ) {
callback( xhr.status, {} ); // since it was checked before this should never happen
},
success: function ( html, status, xhr ) {
if ( !contentTypeRegEx.test( xhr.getResponseHeader( "Content-Type" ) ) ) {
callback( xhr.status, {} ); // since it was checked before this should never happen
return;
};
var content = {};
$( html ).find( "#table td" ).closest( "tr" ).each( function () {
var path = pathCache.getPathForTableRow( pathname, this );
if ( path.isFolder && ( !path.isParentFolder || includeParent ) ) {
content[path.absHref] = path;
THIS.updatePath( path );
};
} );
callback( "h5ai", content );
}
} );
} );
};
var pathnameStatusCache = {};
this.fetchStatus = function ( pathname, callback ) {
if ( h5ai.config.folderStatus[ pathname ] !== undefined ) {
callback( h5ai.config.folderStatus[ pathname ] );
return;
} else if ( pathnameStatusCache[ pathname ] !== undefined ) {
callback( pathnameStatusCache[ pathname ] );
return;
};
$.ajax( {
url: pathname,
type: "HEAD",
complete: function ( xhr ) {
var status = xhr.status;
if ( status === 200 && contentTypeRegEx.test( xhr.getResponseHeader( "Content-Type" ) ) ) {
status = "h5ai";
};
pathnameStatusCache[ pathname ] = status;
callback( status );
}
} );
};
};

View File

@@ -1,3 +1,44 @@
( function( $ ) {
// @include "inc/jquery.json.min.js" // @include "inc/jquery.json.min.js"
// @include "inc/path.js"
// @include "inc/h5ai.js" // @include "inc/h5ai.js"
// #not#include "inc/h5aitree.js" // @include "inc/tree.js"
/*******************************
* create
*******************************/
var pathCache = new PathCache();
var h5ai = new H5ai( h5aiOptions, h5aiLangs, pathCache );
var tree = new Tree( pathCache, h5ai );
/*******************************
* register public api
*******************************/
$.h5ai = {
click: $.proxy( h5ai.pathClick, h5ai )
};
$( ".l10n-footerUsing" ).click( function () {
console.log( "clean" );
pathCache.cache = {};
console.log( "store" );
pathCache.storeCache();
console.log( "load", pathCache.loadCache() );
} );
/*******************************
* init after dom load
*******************************/
$( function() {
h5ai.init();
tree.init();
} );
} )( jQuery );

126
src/h5ai/options.js Normal file
View File

@@ -0,0 +1,126 @@
/*
* h5ai %BUILD_VERSION%
* Options and localization
*/
h5aiOptions = {
/*
* An array of view modes the user may choose from. Currently there
* are two possible values: "details" and "icons". The first value
* indicates the default view mode. If only one value is given the
* view mode is fixed and the selector buttons are hidden.
* The user selected view mode is also stored local in modern browsers
* so that it will be persistent.
*/
viewmodes: [ "details", "icons" ],
/*
* Show a folder tree, boolean.
* Note that this tree might have side effects as it sends HEAD requests
* to the folders, and therefore will invoke index.php scripts. Use
* folderStatus below to avoid such requests.
* It might also affect performance significantly.
*/
showTree: true,
/*
* Associative array of folders and their HTTP status codes to
* avoid HEAD requests to that folders. The key (folder) must start
* and end with a slash (/).
* For example:
* "/some/folder/": 200
* will always return HTTP status 200 (OK), which will be interpreted
* as a non auto indexed folder, that means a folder containing an
* appropriate default index file.
*/
folderStatus: {
/*
* for example:
* "/some/folder/": 200
*/
},
/*
* Localization, for example "en", "de" etc. - see h5aiLangs below for
* possible values. Adjust it to your needs. If lang is not found in
* h5aiLangs the displayed labels stay unchanged.
*/
lang: undefined,
/*
* Try to use browser language, falls back to previous specified lang.
*/
useBrowserLang: true,
/*
* Set parent folder labels to real folder names.
*/
setParentFolderLabels: true,
/*
* Link the hover effects between crumb, extended view and tree.
*/
linkHoverStates: true
};
/*
* Available translations.
* "en" is just an example - see it as a reference. Those values
* are "hardcoded" and will be displayed if all labels stay unchanged.
*/
h5aiLangs = {
"en": {
viewDetails: "details",
viewIcons: "icons",
columnName: "Name",
columnLastModified: "Last modified",
columnSize: "Size",
footerUsing: "using",
parentDirectory: "Parent Directory"
},
"de": {
viewDetails: "Details",
viewIcons: "Icons",
columnName: "Name",
columnLastModified: "Geändert",
columnSize: "Größe",
footerUsing: "nutzt",
parentDirectory: "Übergeordnetes Verzeichnis"
},
"fr": {
viewDetails: "détails",
viewIcons: "icônes",
columnName: "Nom",
columnLastModified: "Dernière modification",
columnSize: "Taille",
footerUsing: "utilise",
parentDirectory: "Dossier parent"
},
"nl": {
viewDetails: "details",
viewIcons: "iconen",
columnName: "Naam",
columnLastModified: "Laatste wijziging",
columnSize: "Grootte",
footerUsing: "gebruikt",
parentDirectory: "Bovenliggende map"
},
"sv": {
viewDetails: "detaljerad",
viewIcons: "ikoner",
columnName: "Filnamn",
columnLastModified: "Senast ändrad",
columnSize: "Filstorlek",
footerUsing: "använder",
parentDirectory: "Till överordnad mapp"
}
};

View File

@@ -1,5 +1,5 @@
################################ ################################
# h5ai 0.5.2 # h5ai 0.9
# customized .htaccess # customized .htaccess
################################ ################################
@@ -56,7 +56,7 @@
IndexOrderDefault Ascending Name IndexOrderDefault Ascending Name
IndexOptions Type=text/html;h5ai=0.5.2 IndexOptions Type=text/html;h5ai=0.9
IndexOptions Charset=UTF-8 IndexOptions Charset=UTF-8
IndexOptions FancyIndexing IndexOptions FancyIndexing
IndexOptions HTMLTable IndexOptions HTMLTable

File diff suppressed because one or more lines are too long

View File

@@ -11,12 +11,13 @@
<img class="techclass" src="/h5ai/images/html5-storage.png" alt="html5-storage" /> <img class="techclass" src="/h5ai/images/html5-storage.png" alt="html5-storage" />
<img class="techclass" src="/h5ai/images/html5-css3.png" alt="html5-css3" /> <img class="techclass" src="/h5ai/images/html5-css3.png" alt="html5-css3" />
</a> </a>
<a href="http://larsjung.de/h5ai" target="_blank" title="h5ai 0.5.2">h5ai</a> <a href="http://larsjung.de/h5ai" target="_blank" title="h5ai 0.9">h5ai 0.9</a>
using <span class="l10n-footerUsing">using</span>
<a href="http://tiheum.deviantart.com/art/Faenza-Icons-173323228" target="_blank" title="icon theme for Gnome">Faenza icons</a> <a href="http://tiheum.deviantart.com/art/Faenza-Icons-173323228" target="_blank" title="icon theme for Gnome">Faenza icons</a>
</footer> </footer>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script>window.jQuery || document.write( '<script src="/h5ai/js/lib/jquery.min.js"><\/script>' )</script> <script>window.jQuery || document.write( '<script src="/h5ai/js/lib/jquery.min.js"><\/script>' )</script>
<script src="/h5ai/options.js"></script>
<script src="/h5ai/js/main.js"></script> <script src="/h5ai/js/main.js"></script>
</body> </body>
</html> </html>

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Directory index · styled with h5ai</title> <title>Directory index · styled with h5ai</title>
<meta name="h5ai-version" content="h5ai 0.5.2"> <meta name="h5ai-version" content="h5ai 0.9">
<meta name="description" content="Directory index styled with h5ai (http://larsjung.de/h5ai)"> <meta name="description" content="Directory index styled with h5ai (http://larsjung.de/h5ai)">
<meta name="keywords" content="directory, index, autoindex, h5ai"> <meta name="keywords" content="directory, index, autoindex, h5ai">
<link rel="shortcut icon" type="image/png" href="/h5ai/images/h5ai-16x16.png"> <link rel="shortcut icon" type="image/png" href="/h5ai/images/h5ai-16x16.png">
@@ -13,14 +13,16 @@
<script src="/h5ai/js/lib/modernizr.min.js"></script> <script src="/h5ai/js/lib/modernizr.min.js"></script>
</head> </head>
<body> <body>
<nav> <nav class="clearfix">
<span class="jsDisabledFallback">Directory index · JavaScript is disabled</span> <span class="jsDisabledFallback">Directory index · JavaScript is disabled</span>
<ul> <ul>
<li id="domain" class="crumb"><a href="/"><img src="/h5ai/images/home.png" alt="domain" /><span>domain</span></a></li> <li id="viewicons" class="view">
<li id="viewicons" class="view"><a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" />icons</a></li> <a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" /><span class="l10n-viewIcons">icons</span></a>
<li id="viewdetails" class="view" ><a href="#"><img src="/h5ai/images/view-details.png" alt="view-details" />details</a></li> </li>
<li id="viewdetails" class="view" >
<a href="#"><img src="/h5ai/images/view-details.png" alt="view-details" /><span class="l10n-viewDetails">details</span></a>
</li>
</ul> </ul>
<div class="clearfix"></div>
</nav> </nav>
<section id="content"> <section id="content">
<header></header> <header></header>

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

View File

Before

Width:  |  Height:  |  Size: 441 B

After

Width:  |  Height:  |  Size: 441 B

View File

Before

Width:  |  Height:  |  Size: 587 B

After

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 B

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 697 B

BIN
target/h5ai/images/tree.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

File diff suppressed because one or more lines are too long

126
target/h5ai/options.js Normal file
View File

@@ -0,0 +1,126 @@
/*
* h5ai 0.9
* Options and localization
*/
h5aiOptions = {
/*
* An array of view modes the user may choose from. Currently there
* are two possible values: "details" and "icons". The first value
* indicates the default view mode. If only one value is given the
* view mode is fixed and the selector buttons are hidden.
* The user selected view mode is also stored local in modern browsers
* so that it will be persistent.
*/
viewmodes: [ "details", "icons" ],
/*
* Show a folder tree, boolean.
* Note that this tree might have side effects as it sends HEAD requests
* to the folders, and therefore will invoke index.php scripts. Use
* folderStatus below to avoid such requests.
* It might also affect performance significantly.
*/
showTree: true,
/*
* Associative array of folders and their HTTP status codes to
* avoid HEAD requests to that folders. The key (folder) must start
* and end with a slash (/).
* For example:
* "/some/folder/": 200
* will always return HTTP status 200 (OK), which will be interpreted
* as a non auto indexed folder, that means a folder containing an
* appropriate default index file.
*/
folderStatus: {
/*
* for example:
* "/some/folder/": 200
*/
},
/*
* Localization, for example "en", "de" etc. - see h5aiLangs below for
* possible values. Adjust it to your needs. If lang is not found in
* h5aiLangs the displayed labels stay unchanged.
*/
lang: undefined,
/*
* Try to use browser language, falls back to previous specified lang.
*/
useBrowserLang: true,
/*
* Set parent folder labels to real folder names.
*/
setParentFolderLabels: true,
/*
* Link the hover effects between crumb, extended view and tree.
*/
linkHoverStates: true
};
/*
* Available translations.
* "en" is just an example - see it as a reference. Those values
* are "hardcoded" and will be displayed if all labels stay unchanged.
*/
h5aiLangs = {
"en": {
viewDetails: "details",
viewIcons: "icons",
columnName: "Name",
columnLastModified: "Last modified",
columnSize: "Size",
footerUsing: "using",
parentDirectory: "Parent Directory"
},
"de": {
viewDetails: "Details",
viewIcons: "Icons",
columnName: "Name",
columnLastModified: "Geändert",
columnSize: "Größe",
footerUsing: "nutzt",
parentDirectory: "Übergeordnetes Verzeichnis"
},
"fr": {
viewDetails: "détails",
viewIcons: "icônes",
columnName: "Nom",
columnLastModified: "Dernière modification",
columnSize: "Taille",
footerUsing: "utilise",
parentDirectory: "Dossier parent"
},
"nl": {
viewDetails: "details",
viewIcons: "iconen",
columnName: "Naam",
columnLastModified: "Laatste wijziging",
columnSize: "Grootte",
footerUsing: "gebruikt",
parentDirectory: "Bovenliggende map"
},
"sv": {
viewDetails: "detaljerad",
viewIcons: "ikoner",
columnName: "Filnamn",
columnLastModified: "Senast ändrad",
columnSize: "Filstorlek",
footerUsing: "använder",
parentDirectory: "Till överordnad mapp"
}
};