1
0
mirror of https://github.com/lrsjng/h5ai.git synced 2025-09-02 02:12:43 +02:00

Compare commits

...

12 Commits
v0.5.3 ... 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
46 changed files with 1137 additions and 525 deletions

View File

@@ -1,14 +1,14 @@
# h5ai v0.5.3   ·   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,11 +47,49 @@ 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 ### v0.5.3
*2011-07-04* *2011-07-04*
* refactored js * refactored js
* added basic options support * added basic options support via `options.js`
* commented `options.js`
* optional tree sidebar
### v0.5.2 ### v0.5.2

View File

@@ -3,7 +3,7 @@ custom = true
# project # project
project.name = h5ai project.name = h5ai
project.version = 0.5.3 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,38 +12,58 @@
white-space: nowrap; white-space: nowrap;
clear: both; clear: both;
&.header a { &.header {
padding-bottom: 18px; a, a:active, a:visited {
color: #555; padding-bottom: 18px;
opacity: 0.4;
cursor: pointer;
.transition( all 0.2s ease-in-out );
&:visited {
color: #555; color: #555;
} text-decoration: none;
&:hover { opacity: 0.4;
color: #555; cursor: pointer;
opacity: 0.9; .transition( all 0.2s ease-in-out );
}
img { &:hover {
width: 12px; color: #555;
height: 12px; opacity: 0.9;
padding: 0 8px; }
img {
width: 12px;
height: 12px;
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;
}
}
.hint {
color: #c55;
} }
} }
ul { .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,45 +40,27 @@ 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 {
float: left;
border-right: 1px dotted rgb(225,225,225);
.hint {
margin-left: 8px;
font-style: italic;
color: #999;
}
img.hint {
width: 10px;
height: 10px;
vertical-align: baseline;
padding: 0px;
}
}
&.current {
background-color: rgba(255,255,255,0.5);
opacity: 1.0;
}
&.view {
float: right;
border-left: 1px dotted rgb(225,225,225);
}
&:hover, &:hover a {
background-color: rgba(255,255,255,0.5);
color: #e80;
opacity: 1.0;
}
}
a {
display: block; display: block;
height: 30px; height: 30px;
line-height: 30px; line-height: 30px;
padding: 0 10px; 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 { img {
width: 16px; width: 16px;
@@ -96,11 +68,30 @@ body > nav {
vertical-align: bottom; vertical-align: bottom;
padding: 0 6px 6px 0; padding: 0 6px 6px 0;
} }
.crumb {
float: left;
border-right: 1px solid rgb(231,231,231);
.hint {
margin-left: 8px;
font-style: italic;
color: #999;
}
img.hint {
width: 10px;
height: 10px;
vertical-align: baseline;
padding: 0px;
}
}
.view {
float: right;
border-left: 1px solid rgb(231,231,231);
}
} }
#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,8 +11,8 @@
<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.6.1/jquery.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>

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,99 +0,0 @@
var File = function ( utils, folder, tableRow ) {
if ( ! /\/$/.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 = utils.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;
};
};

View File

@@ -1,32 +1,30 @@
var H5ai = function ( options ) { var H5ai = function ( options, langs, pathCache ) {
/******************************* /*******************************
* config * config
*******************************/ *******************************/
var defaults = { var defaults = {
columnClasses: [ "icon", "name", "date", "size" ],
defaultSortOrder: "C=N;O=A", defaultSortOrder: "C=N;O=A",
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" ], viewmodes: [ "details", "icons" ],
showTree: false, showTree: false,
folderStatus: { folderStatus: {
} },
lang: undefined,
useBrowserLang: true,
setParentFolderLabels: true,
linkHoverStates: true
}; };
this.config = $.extend( {}, defaults, options ); this.config = $.extend( {}, defaults, options );
@@ -35,20 +33,11 @@ var H5ai = function ( options ) {
/******************************* /*******************************
* public api * public api
*******************************/ *******************************/
this.folderClick = function ( fn ) {
if ( typeof fn === "function" ) { this.pathClick = function ( fn ) {
this.config.callbacks.folderClick.push( fn );
};
return this;
};
if ( $.isFunction( fn ) ) {
this.fileClick = function ( fn ) { this.config.callbacks.pathClick.push( fn );
if ( typeof fn === "function" ) {
this.config.callbacks.fileClick.push( fn );
}; };
return this; return this;
}; };
@@ -61,10 +50,14 @@ var H5ai = function ( options ) {
this.init = function () { this.init = function () {
document.title = document.domain + decodeURI( document.location.pathname );
this.applyViewmode(); this.applyViewmode();
this.initBreadcrumb(); this.initBreadcrumb();
this.initTopSpace();
this.initViews(); this.initViews();
this.customize(); this.customize();
this.localize( langs, this.config.lang, this.config.useBrowserLang );
}; };
@@ -73,18 +66,10 @@ var H5ai = function ( options ) {
* callback triggers * callback triggers
*******************************/ *******************************/
this.triggerFolderClick = function ( label ) { this.triggerPathClick = function ( path, context ) {
for ( idx in this.config.callbacks.folderClick ) { for ( idx in this.config.callbacks.pathClick ) {
this.config.callbacks.folderClick[idx].call( window, label ); this.config.callbacks.pathClick[idx].call( window, path, context );
};
};
this.triggerFileClick = function ( label ) {
for ( idx in this.config.callbacks.fileClick ) {
this.config.callbacks.fileClick[idx].call( window, label );
}; };
}; };
@@ -97,10 +82,7 @@ var H5ai = function ( options ) {
this.getViewmode = function () { this.getViewmode = function () {
var viewmode = localStorage.getItem( this.config.store.viewmode ); var viewmode = localStorage.getItem( this.config.store.viewmode );
if ( $.inArray( viewmode, this.config.viewmodes ) >= 0 ) { return $.inArray( viewmode, this.config.viewmodes ) >= 0 ? viewmode : this.config.viewmodes[0];
return viewmode;
};
return this.config.viewmodes[0];
}; };
@@ -109,8 +91,10 @@ var H5ai = function ( options ) {
if ( viewmode !== undefined ) { if ( viewmode !== undefined ) {
localStorage.setItem( this.config.store.viewmode, viewmode ); localStorage.setItem( this.config.store.viewmode, viewmode );
}; };
viewmode = this.getViewmode();
$( "body > nav li.view" ).hide(); $( "body > nav li.view" ).hide().removeClass( "current" );
if ( this.config.viewmodes.length > 1 ) { if ( this.config.viewmodes.length > 1 ) {
if ( $.inArray( "details", this.config.viewmodes ) >= 0 ) { if ( $.inArray( "details", this.config.viewmodes ) >= 0 ) {
$( "#viewdetails" ).show(); $( "#viewdetails" ).show();
@@ -120,12 +104,11 @@ var H5ai = function ( options ) {
}; };
}; };
$( "body > nav li.view" ).removeClass( "current" ); if ( viewmode === "details" ) {
if ( this.getViewmode() === "details" ) {
$( "#viewdetails" ).closest( "li" ).addClass( "current" ); $( "#viewdetails" ).closest( "li" ).addClass( "current" );
$( "#table" ).hide(); $( "#table" ).hide();
$( "#extended" ).addClass( "details-view" ).removeClass( "icons-view" ).show(); $( "#extended" ).addClass( "details-view" ).removeClass( "icons-view" ).show();
} else if ( this.getViewmode() === "icons" ) { } else if ( viewmode === "icons" ) {
$( "#viewicons" ).closest( "li" ).addClass( "current" ); $( "#viewicons" ).closest( "li" ).addClass( "current" );
$( "#table" ).hide(); $( "#table" ).hide();
$( "#extended" ).removeClass( "details-view" ).addClass( "icons-view" ).show(); $( "#extended" ).removeClass( "details-view" ).addClass( "icons-view" ).show();
@@ -135,29 +118,60 @@ var H5ai = function ( options ) {
}; };
}; };
/******************************* /*******************************
* breadcrumb and doc title * breadcrumb
*******************************/ *******************************/
this.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='" + this.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();
}; };
@@ -168,22 +182,7 @@ var H5ai = function ( options ) {
this.initTableView = function () { this.initTableView = function () {
var ref = this;
function getColumnClass( idx ) {
if ( idx >= 0 && idx < ref.config.columnClasses.length ) {
return ref.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++ ) );
} );
} );
}; };
@@ -197,14 +196,15 @@ var H5ai = function ( options ) {
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;
@@ -213,9 +213,9 @@ var H5ai = function ( options ) {
}; };
var $icon; var $icon;
if ( order.indexOf( "O=A" ) >= 0 ) { if ( order.indexOf( "O=A" ) >= 0 ) {
$icon = $( "<img src='" + this.config.icons.ascending + "' class='sort' alt='ascending' />" ); $icon = $( "<img src='/h5ai/images/ascending.png' class='sort' alt='ascending' />" );
} else { } else {
$icon = $( "<img src='" + this.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 );
@@ -224,58 +224,26 @@ var H5ai = function ( options ) {
} else if ( order.indexOf( "C=S" ) >= 0 ) { } else if ( order.indexOf( "C=S" ) >= 0 ) {
$li.find( "a.size" ).prepend( $icon ); $li.find( "a.size" ).prepend( $icon );
}; };
// entries
$( "#table td.name a" ).closest( "tr" ).each( function () {
var $tr = $( this );
var $img = $tr.find( "td.icon img" );
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 ); // entries
if ( alt === "[DIR]" ) { $( "#table td" ).closest( "tr" ).each( function () {
$li.addClass( "folder" ); var path = pathCache.getPathForTableRow( decodeURI( document.location.pathname ), this );
} else { $ul.append( path.updateExtendedHtml() );
$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
var ref = this;
$( "#extended .entry.folder" )
.click( function() {
ref.triggerFolderClick( $( this ).find( ".label" ).text() );
} );
$( "#extended .entry.file" )
.click( function() {
ref.triggerFileClick( $( this ).find( ".label" ).text() );
} );
}; };
/******************************* /*******************************
* init views * init views
*******************************/ *******************************/
@@ -285,15 +253,14 @@ var H5ai = function ( options ) {
this.initTableView(); this.initTableView();
this.initExtendedView(); this.initExtendedView();
var ref = this;
$( "#viewdetails" ).closest( "li" ) $( "#viewdetails" ).closest( "li" )
.click( function () { .click( $.proxy( function () {
ref.applyViewmode( "details" ); this.applyViewmode( "details" );
} ); }, this ) );
$( "#viewicons" ).closest( "li" ) $( "#viewicons" ).closest( "li" )
.click( function () { .click( $.proxy( function () {
ref.applyViewmode( "icons" ); this.applyViewmode( "icons" );
} ); }, this ) );
}; };
@@ -320,4 +287,32 @@ var H5ai = function ( options ) {
} }
} ); } );
}; };
/*******************************
* localization
*******************************/
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;
};
};
if ( data[ lang ] !== undefined ) {
var selected = data[ lang ];
for ( key in selected ) {
$( ".l10n-" + key ).text( selected[key] );
};
};
};
}; };

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;
};
};

View File

@@ -1,183 +1,154 @@
var Tree = function ( utils, h5ai ) { var Tree = function ( pathCache, h5ai ) {
var thistree = this; var THIS = this;
var contentTypeRegEx = /^text\/html;h5ai=/; var contentTypeRegEx = /^text\/html;h5ai=/;
this.init = function () { this.init = function () {
if ( h5ai.config.showTree ) { if ( h5ai.config.showTree ) {
this.checkCrumb(); this.updatePaths();
this.initShifting();
this.populateTree(); this.populateTree();
}; };
}; };
this.checkCrumb = function () { this.updatePath = function ( path ) {
$( "li.crumb a" ).each( function() { if ( path.isFolder && !path.isParentFolder && path.status === undefined ) {
this.fetchStatus( path.absHref, function ( status ) {
var $a = $( this ); if ( status !== "h5ai" ) {
var pathname = $a.attr( "href" ); path.status = status;
thistree.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 );
};
}; };
path.updateHtml();
} ); } );
} );
};
this.shiftTree = function ( show ) {
var $tree = $( "#tree" );
var $extended = $( "#extended" );
var show = show || false;
if ( $tree.outerWidth() < $extended.offset().left || show ) {
$tree.stop().animate( { left: 0 } );
} else {
$tree.stop().animate( { left: 24 - $tree.outerWidth() } );
}; };
}; };
this.initShifting = function () {
this.updatePaths = function () {
$( "#tree" ).hover(
function () { for ( var ref in pathCache.cache ) {
thistree.shiftTree( true ); this.updatePath( pathCache.cache[ref] );
}, };
function () {
thistree.shiftTree();
}
);
$( window ).resize( function() {
thistree.shiftTree();
} );
}; };
this.populateTree = function () { this.populateTree = function () {
var $tree = $( "#tree" ); var $tree = $( "#tree" );
$tree.css( { left: -400 } ).show(); var $extended = $( "#extended" );
var shiftTree = function ( show ) {
this.shiftTree(); if ( $tree.outerWidth() < $extended.offset().left || show === true ) {
$tree.stop().animate( { left: 0 } );
this.fetchTree( decodeURI( document.location.pathname ), function( entry ) {
$tree.empty().append( entry.toHtml() );
thistree.shiftTree();
} );
};
this.fetchTree = function ( pathname, callback ) {
this.walkBack( pathname, function( walkbackedPathname ) {
var entry = new File( utils, walkbackedPathname );
thistree.fetchEntriesRecursive( walkbackedPathname, function ( content ) {
entry.content = content;
callback( entry );
} );
} );
};
this.walkBack = function ( pathname, callback ) {
var splits = utils.splitPathname( pathname );
var parent = splits[0];
if ( parent === "" ) {
callback( pathname );
} else {
this.checkPathname( parent, function( state ) {
if ( state === 0 ) {
thistree.walkBack( parent, callback );
} else {
callback( pathname );
};
} );
};
};
this.fetchEntriesRecursive = function ( pathname, callback ) {
this.fetchEntries( pathname, false, function ( entries ) {
if ( entries instanceof Array ) {
for ( idx in entries ) {
( function ( entry ) {
if ( entry.isFolder ) {
thistree.fetchEntriesRecursive( entry.absHref, function( content ) {
entry.content = content;
callback( entries );
} );
};
} ) ( entries[idx] );
};
};
callback( entries );
} );
};
this.fetchEntries = function ( pathname, includeParent, callback ) {
this.checkPathname( pathname, function ( status ) {
console.log( "checkPathname", pathname, status );
if ( status !== 0 ) {
callback( status );
} else { } else {
$.ajax( { $tree.stop().animate( { left: 18 - $tree.outerWidth() } );
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 File( utils, pathname, this );
if ( !entry.isParentFolder || includeParent ) {
entries.push( entry );
};
} );
callback( entries );
};
}
} );
}; };
};
$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.checkPathname = function ( pathname, callback ) { 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 ) { if ( h5ai.config.folderStatus[ pathname ] !== undefined ) {
callback( h5ai.config.folderStatus[ pathname ] ); callback( h5ai.config.folderStatus[ pathname ] );
} else { return;
$.ajax( { } else if ( pathnameStatusCache[ pathname ] !== undefined ) {
url: pathname, callback( pathnameStatusCache[ pathname ] );
type: "HEAD", return;
complete: function ( xhr ) {
if ( xhr.status === 200 && contentTypeRegEx.test( xhr.getResponseHeader( "Content-Type" ) ) ) {
callback( 0 );
} else {
callback( xhr.status );
};
}
} );
}; };
$.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,15 +0,0 @@
var Utils = function () {
var pathnameRegEx = /^(\/(.*\/)*)([^\/]+\/?)$/;
this.splitPathname = function ( pathname ) {
if ( pathname === "/" ) {
return [ "", "/" ];
};
var match = pathnameRegEx.exec( pathname );
return [ match[1], match[3] ];
};
};

View File

@@ -1,8 +1,8 @@
( function( $ ) { ( function( $ ) {
// @include "inc/utils.js" // @include "inc/jquery.json.min.js"
// @include "inc/path.js"
// @include "inc/h5ai.js" // @include "inc/h5ai.js"
// @include "inc/file.js"
// @include "inc/tree.js" // @include "inc/tree.js"
@@ -10,9 +10,9 @@
* create * create
*******************************/ *******************************/
var utils = new Utils(); var pathCache = new PathCache();
var h5ai = new H5ai( h5aiOptions ); var h5ai = new H5ai( h5aiOptions, h5aiLangs, pathCache );
var tree = new Tree( utils, h5ai ); var tree = new Tree( pathCache, h5ai );
/******************************* /*******************************
@@ -20,11 +20,18 @@
*******************************/ *******************************/
$.h5ai = { $.h5ai = {
folderClick: h5ai.folderClick, click: $.proxy( h5ai.pathClick, h5ai )
fileClick: h5ai.fileClick
}; };
$( ".l10n-footerUsing" ).click( function () {
console.log( "clean" );
pathCache.cache = {};
console.log( "store" );
pathCache.storeCache();
console.log( "load", pathCache.loadCache() );
} );
/******************************* /*******************************
* init after dom load * init after dom load
*******************************/ *******************************/

View File

@@ -1,8 +1,126 @@
/*
* h5ai %BUILD_VERSION%
* Options and localization
*/
h5aiOptions = { h5aiOptions = {
viewmodes: [ "icons", "details" ],
/*
* 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, 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: { folderStatus: {
"/develop/folder-types/phpsite/": 200 /*
} * 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.3 # h5ai 0.9
# customized .htaccess # customized .htaccess
################################ ################################
@@ -56,7 +56,7 @@
IndexOrderDefault Ascending Name IndexOrderDefault Ascending Name
IndexOptions Type=text/html;h5ai=0.5.3 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,8 +11,8 @@
<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.3">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.6.1/jquery.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>

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.3"> <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

View File

@@ -1,8 +1,126 @@
/*
* h5ai 0.9
* Options and localization
*/
h5aiOptions = { h5aiOptions = {
viewmodes: [ "icons", "details" ],
/*
* 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, 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: { folderStatus: {
"/develop/folder-types/phpsite/": 200 /*
} * 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"
}
}; };