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

Compare commits

...

15 Commits
v0.4 ... v0.8

Author SHA1 Message Date
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
Lars Jung
b7387adfc8 Some fixes. 2011-07-02 21:11:25 +02:00
Lars Jung
8ee98ed7bd Disabled tree. 2011-07-01 15:32:22 +02:00
Lars Jung
067e0970f8 Added tree sidebar. 2011-07-01 01:51:24 +02:00
Lars Jung
13ddb670b8 Updated screenshots and readme. 2011-06-27 16:13:07 +02:00
44 changed files with 1446 additions and 548 deletions

4
.gitignore vendored
View File

@@ -3,7 +3,9 @@
bin bin
build build
#target #target
build.local.xml
build.local.*
# Eclipse # Eclipse
.classpath .classpath

View File

@@ -1,14 +1,14 @@
# h5ai v0.3.2   ·   a beautified Apache index # h5ai v0.8   ·   a beautified Apache index
## Screenshots ## Screenshots
<a href="http://github.com/lrsjng/h5ai/raw/master/resources/h5ai-v0.2.1-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.2.1-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.2.1-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.2.1-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,22 +24,19 @@ 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
will be wrapped by `<header>` and `<footer>` tags. will be wrapped by `<header>` and `<footer>` tags.
## References and License ## License and References
[h5ai](http://larsjung.de/h5ai)
[h5ai on GitHub](http://github.com/lrsjng/h5ai)
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a> <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a>
This project is provided under the terms of the [CC BY-SA 3.0 License](http://creativecommons.org/licenses/by-sa/3.0/). [h5ai](http://larsjung.de/h5ai) is provided under the terms of the [CC BY-SA 3.0 License](http://creativecommons.org/licenses/by-sa/3.0/).
It is based on It is based on
[HTML5 Boilerplate](http://html5boilerplate.com), [HTML5 Boilerplate](http://html5boilerplate.com),
[jQuery](http://jquery.com), [jQuery](http://jquery.com),
@@ -50,6 +47,59 @@ please respect their rights.
## Changelog ## Changelog
### 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
*2011-07-02*
* details view adjusts to window width
* linked icon for *.gz and *.bz2
### v0.5.1
*2011-07-01*
* disabled tree sidebar for now, since it had unwanted side effects
### v0.5
*2011-07-01*
* added tree sidebar
* some refactorings
### v0.4 ### v0.4
*2011-06-27* *2011-06-27*

View File

@@ -3,7 +3,7 @@ custom = true
# project # project
project.name = h5ai project.name = h5ai
project.version = 0.4 project.version = 0.8
# 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: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

View File

@@ -8,14 +8,16 @@
# Options +FollowSymLinks # Options +FollowSymLinks
################################
# cache images for 52 weeks
################################
<IfModule mod_headers.c> <IfModule mod_headers.c>
################################
# cache images for 52 weeks
################################
<FilesMatch "\.png$"> <FilesMatch "\.png$">
Header set Cache-Control "max-age=31449600, public" Header set Cache-Control "max-age=31449600, public"
</FilesMatch> </FilesMatch>
</IfModule> </IfModule>
@@ -54,6 +56,7 @@
IndexOrderDefault Ascending Name IndexOrderDefault Ascending Name
IndexOptions Type=text/html;h5ai=%BUILD_VERSION%
IndexOptions Charset=UTF-8 IndexOptions Charset=UTF-8
IndexOptions FancyIndexing IndexOptions FancyIndexing
IndexOptions HTMLTable IndexOptions HTMLTable
@@ -87,9 +90,9 @@
AddIcon /h5ai/icons/16x16/makefile.png .pom pom.xml build.xml AddIcon /h5ai/icons/16x16/makefile.png .pom pom.xml build.xml
AddIcon /h5ai/icons/16x16/bin.png .so .o AddIcon /h5ai/icons/16x16/bin.png .so .o
AddIcon /h5ai/icons/16x16/zip.png .zip .Z .z .jar .war
AddIcon /h5ai/icons/16x16/tar.png .tar
AddIcon /h5ai/icons/16x16/archive.png .tar.gz .tgz .tar.bz2 AddIcon /h5ai/icons/16x16/archive.png .tar.gz .tgz .tar.bz2
AddIcon /h5ai/icons/16x16/zip.png .zip .Z .z .jar .war .gz .bz2
AddIcon /h5ai/icons/16x16/tar.png .tar
AddIcon /h5ai/icons/16x16/pdf.png .pdf AddIcon /h5ai/icons/16x16/pdf.png .pdf
AddIcon /h5ai/icons/16x16/deb.png .deb AddIcon /h5ai/icons/16x16/deb.png .deb
AddIcon /h5ai/icons/16x16/rpm.png .rpm AddIcon /h5ai/icons/16x16/rpm.png .rpm

View File

@@ -1,86 +1,108 @@
#extended.details-view { #extended.details-view {
display: none; display: none;
ul { ul {
margin: 0; margin: 0;
padding: 0; padding: 0;
list-style: none; list-style: none;
}
li {
white-space: nowrap;
}
li.header a {
padding-bottom: 18px;
color: #555;
opacity: 0.4;
cursor: pointer;
.transition( all 0.2s ease-in-out );
&:visited { li {
color: #555; position: relative;
} white-space: nowrap;
&:hover { clear: both;
color: #555;
opacity: 0.9; &.header a {
} padding-bottom: 18px;
img { color: #555;
width: 12px; opacity: 0.4;
height: 12px; cursor: pointer;
padding: 0 8px; .transition( all 0.2s ease-in-out );
}
} &:visited {
li.entry { color: #555;
display: block; }
border-bottom: 1px solid #ddd; &:hover {
&:first-child { color: #555;
border-top: 1px solid #ddd; opacity: 0.9;
} }
a, a:hover { img {
display: block; width: 12px;
cursor: pointer; height: 12px;
&:hover { padding: 0 8px;
background-color: #f0f0f0; }
color: #e80; }
&.entry {
border-bottom: 1px solid #ddd;
a {
display: block;
cursor: pointer;
&:hover {
background-color: #f6f6f6;
color: #e80;
}
}
&.error {
> a, > a:visited {
color: #999;
.label {
opacity: 0.7;
.hint {
font-size: 0.9em;
font-style: italic;
color: #c55;
}
}
}
}
}
.icon, .label, .date, .size {
padding: 6px;
}
.icon {
display: inline-block;
position: absolute;
left: 0;
top: 2px;
width: 16px;
img {
width: 16px;
height: 16px;
}
}
.icon.big {
display: none;
}
.label {
display: block;
margin: 0 270px 0 24px;
overflow: hidden;
white-space: nowrap;
text-align: left;
}
.date {
position: absolute;
right: 100px;
top: 0;
text-align: right;
width: 160px;
white-space: nowrap;
}
.size {
position: absolute;
right: 0;
top: 0;
text-align: right;
width: 80px;
white-space: nowrap;
} }
} }
} }
.icon, .label, .date, .size {
display: inline-block;
padding: 3px 6px 6px 6px;
text-align: left;
border: none;
}
.icon {
text-align: center;
width: 16px;
img {
padding-top: 4px;
width: 16px;
height: 16px;
}
}
.icon.big {
display: none;
}
.label {
width: 682px;
max-width: 682px;
overflow: hidden;
white-space: nowrap;
}
.date {
text-align: right;
width: 160px;
min-width: 160px;
white-space: nowrap;
}
.size {
text-align: right;
width: 70px;
min-width: 70px;
white-space: nowrap;
}
.empty { .empty {
text-align: center; text-align: center;
margin: 50px 0; margin: 50px 0;
@@ -101,47 +123,67 @@
margin: 0; margin: 0;
padding: 0; padding: 0;
list-style: none; list-style: none;
}
li.header {
display: none;
}
li.entry {
float: left;
a { li {
display: block; &.header {
margin: 8px; display: none;
padding: 8px;
width: 100px;
height: 120px;
float: left;
text-align: center;
overflow: hidden;
border-radius: 5px;
cursor: pointer;
border: 1px solid rgba(0,0,0,0);
&:hover {
color: #e80;
border-color: #eee;
.box-shadow( 0, 0, 20px, #999 );
} }
.icon { &.entry {
display: block; float: left;
img {
width: 48px; a {
height: 48px; display: block;
margin-bottom: 8px; margin: 8px;
padding: 8px;
width: 100px;
height: 120px;
float: left;
text-align: center;
overflow: hidden;
border-radius: 5px;
cursor: pointer;
border: 2px solid rgba(0,0,0,0);
&:hover {
color: #e80;
border-color: #eee;
background-color: #f6f6f6;
}
.icon {
display: block;
img {
width: 48px;
height: 48px;
margin-bottom: 8px;
}
}
.icon.small {
display: none;
}
.label {
display: block;
word-wrap: break-word;
}
.date, .size {
display: none;
}
}
&.error {
> a, > a:visited {
color: #999;
.label {
opacity: 0.7;
.hint {
font-size: 0.9em;
font-style: italic;
color: #c55;
}
}
}
} }
}
.icon.small {
display: none;
}
.label {
display: block;
}
.date, .size {
display: none;
} }
} }
} }

View File

@@ -1,46 +1,32 @@
.border-radius ( @radius: 5px ) { .border-radius ( @radius ) {
-moz-border-radius: @radius; -moz-border-radius: @radius;
-webkit-border-radius: @radius; -webkit-border-radius: @radius;
border-radius: @radius; border-radius: @radius;
} }
.border-top-right-radius ( @radius: 5px ) { .box-shadow ( @shadow ) {
-moz-border-radius-topright: @radius; -moz-box-shadow: @shadow;
-webkit-border-top-right-radius: @radius; -webkit-box-shadow: @shadow;
border-top-right-radius: @radius; box-shadow: @shadow;
} }
.border-bottom-right-radius ( @radius: 5px ) { .transition ( @transition ) {
-moz-border-radius-bottomright: @radius; -moz-transition: @transition;
-webkit-border-bottom-right-radius: @radius; -ms-transition: @transition;
border-bottom-right-radius: @radius; -o-transition: @transition;
-webkit-transition: @transition;
transition: @transition;
} }
.box-shadow ( @x: 10px, @y: 10px, @blur: 5px, @color: #ccc ) { .transform ( @transform ) {
-moz-box-shadow: @x @y @blur @color; -moz-transform: @transform;
-webkit-box-shadow: @x @y @blur @color; -o-transform: @transform;
box-shadow: @x @y @blur @color; -webkit-transform: @transform;
} transform: @transform;
.transition ( @transitions ) {
-moz-transition: @transitions;
-ms-transition: @transitions;
-o-transition: @transitions;
-webkit-transition: @transitions;
transition: @transitions;
}
.transform ( @transforms ) {
-moz-transform: @transforms;
-o-transform: @transforms;
-webkit-transform: @transforms;
transform: @transforms;
} }
@@ -50,46 +36,3 @@
background-size: @size; background-size: @size;
} }
.rhythm ( @height, @size ) {
@base: @size / 16;
font-size: 1% * @base * 100;
@factor: @height / @size;
@rhythm: 1em * @factor;
p {
font-size: 1em;
line-height: @rhythm;
margin-top: @rhythm;
margin-bottom: @rhythm;
}
h1 {
font-size: @rhythm;
line-height: 1em;
margin-bottom: 1em;
margin-top: 1em;
}
h2 {
font-size: @rhythm / 1.1;
line-height: 1.1em;
margin-bottom: 1.1em;
margin-top: 1.1em;
}
h3 {
font-size: @rhythm / 1.2;
line-height: 1.2em;
margin-bottom: 1.2em;
margin-top: 1.2em;
}
h4 {
font-size: @rhythm / 1.3;
line-height: 1.3em;
margin-bottom: 1.3em;
margin-top: 1.3em;
}
}

106
src/h5ai/css/inc/tree.less Normal file
View File

@@ -0,0 +1,106 @@
#tree {
position: fixed;
left: -200px;
top: 80px;
font-size: 0.85em;
padding: 16px 32px 16px 16px;
background-color: rgb(241,241,241);
border: 2px solid rgb(210,210,210);
border-left: none;
.border-radius ( 0 15px 15px 0 );
.entry {
.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.visited {
margin-left: 16px;
padding: 4px 6px;
border: 1px solid rgba(0,0,0,0);
.border-radius( 5px );
display: block;
opacity: 0.7;
&:hover {
background-color: rgba(255,255,255,0.5);
opacity: 1;
}
.label {
display: inline-block;
}
.icon {
display: inline-block;
width: 20px;
img {
width: 16px;
height: 16px;
vertical-align: bottom;
}
}
.hint {
display: inline-block;
margin-left: 12px;
font-style: italic;
font-size: 0.9em;
color: #ccc;
img {
width: 10px;
height: 10px;
vertical-align: baseline;
}
}
}
&.file {
display: none;
}
&.current {
> a, > a:visited {
border: 1px solid rgba(0,0,0,0.1);
background-color: rgba(255,255,255,0.5);
opacity: 1;
}
}
&.error {
> a, > a:visited {
color: #999;
}
.hint {
color: #c55;
}
}
.content {
list-style: none;
margin-left: 20px;
}
}
}

View File

@@ -39,10 +39,9 @@ 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;
height: 30px; height: 30px;
@@ -57,15 +56,30 @@ body > nav {
&.crumb { &.crumb {
float: left; float: left;
border-right: 1px dotted rgb(225,225,225); 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;
}
}
&.current {
background-color: rgba(255,255,255,0.5);
opacity: 1.0;
} }
&.view { &.view {
float: right; float: right;
border-left: 1px dotted rgb(225,225,225); border-left: 1px solid rgb(230,230,230);
} }
&:hover, &:hover a { &:hover, &:hover a {
color: #e80;
background-color: rgba(255,255,255,0.5); background-color: rgba(255,255,255,0.5);
color: #e80;
opacity: 1.0; opacity: 1.0;
} }
} }
@@ -105,6 +119,7 @@ body > nav {
@import "inc/table"; @import "inc/table";
@import "inc/extended"; @import "inc/extended";
@import "inc/tree";
body > footer { body > footer {
@@ -114,12 +129,12 @@ 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:visited {
color: #555; color: #555;

View File

@@ -3,6 +3,7 @@
<section id="extended"></section> <section id="extended"></section>
<footer></footer> <footer></footer>
</section> </section>
<section id="tree"></section>
<footer> <footer>
<a id="html5" href="http://www.w3.org/html/logo/" target="_blank" title="HTML5 semantics, storage & CSS3"> <a id="html5" href="http://www.w3.org/html/logo/" target="_blank" title="HTML5 semantics, storage & CSS3">
<img class="logo" src="/h5ai/images/html5.png" alt="html5" /> <img class="logo" src="/h5ai/images/html5.png" alt="html5" />
@@ -10,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="%BUILD_NAME% %BUILD_VERSION%">h5ai</a> <a href="http://larsjung.de/h5ai" target="_blank" title="h5ai %BUILD_VERSION%">h5ai</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="%BUILD_NAME% %BUILD_VERSION%"> <meta name="h5ai-version" content="h5ai %BUILD_VERSION%">
<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">
@@ -16,9 +16,15 @@
<nav> <nav>
<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="domain" class="crumb">
<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/home.png" alt="domain" /><span>domain</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="viewicons" class="view">
<a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" /><span class="l10n-viewIcons">icons</span></a>
</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> <div class="clearfix"></div>
</nav> </nav>

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

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: 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

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 B

333
src/h5ai/js/inc/h5ai.js Normal file
View File

@@ -0,0 +1,333 @@
var H5ai = function ( options, langs ) {
var THIS = this;
/*******************************
* config
*******************************/
var defaults = {
defaultSortOrder: "C=N;O=A",
store: {
viewmode: "h5ai.viewmode"
},
icons: {
crumb: "/h5ai/images/crumb.png",
ascending: "/h5ai/images/ascending.png",
descending: "/h5ai/images/descending.png"
},
customHeader: "h5ai.header.html",
customFooter: "h5ai.footer.html",
callbacks: {
folderClick: [],
fileClick: []
},
viewmodes: [ "details", "icons" ],
showTree: false,
folderStatus: {
},
lang: undefined,
useBrowserLang: true,
setParentFolderLabels: true
};
this.config = $.extend( {}, defaults, options );
/*******************************
* public api
*******************************/
this.folderClick = function ( fn ) {
if ( typeof fn === "function" ) {
this.config.callbacks.folderClick.push( fn );
};
return this;
};
this.fileClick = function ( fn ) {
if ( typeof fn === "function" ) {
this.config.callbacks.fileClick.push( fn );
};
return this;
};
/*******************************
* init
*******************************/
this.init = function () {
document.title = document.domain + decodeURI( document.location.pathname );
this.applyViewmode();
this.initBreadcrumb();
this.initTopSpace();
this.initViews();
this.customize();
this.localize( langs, this.config.lang, this.config.useBrowserLang );
};
/*******************************
* callback triggers
*******************************/
this.triggerFolderClick = function ( label ) {
for ( idx in this.config.callbacks.folderClick ) {
this.config.callbacks.folderClick[idx].call( window, label );
};
};
this.triggerFileClick = function ( label ) {
for ( idx in this.config.callbacks.fileClick ) {
this.config.callbacks.fileClick[idx].call( window, label );
};
};
/*******************************
* local stored viewmode
*******************************/
this.getViewmode = function () {
var viewmode = localStorage.getItem( this.config.store.viewmode );
return $.inArray( viewmode, this.config.viewmodes ) >= 0 ? viewmode : this.config.viewmodes[0];
};
this.applyViewmode = function ( viewmode ) {
if ( viewmode !== undefined ) {
localStorage.setItem( this.config.store.viewmode, viewmode );
};
viewmode = this.getViewmode();
$( "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" );
$( "#table" ).hide();
$( "#extended" ).removeClass( "details-view" ).addClass( "icons-view" ).show();
} else {
$( "#table" ).show();
$( "#extended" ).hide();
};
};
/*******************************
* breadcrumb
*******************************/
this.initBreadcrumb = function () {
var $domain = $( "#domain" );
var $ul = $domain.closest( "ul" );
$domain.find( "span" ).text( document.domain );
var pathnameParts = decodeURI( document.location.pathname ).split( "/" );
var pathname = "/";
for ( idx in pathnameParts ) {
var part = pathnameParts[idx];
if ( part !== "" ) {
pathname += part + "/";
var path = pathCache.getPathForFolder( pathname );
$ul.append( path.updateCrumbHtml() );
};
};
};
/*******************************
* top space, depending on nav height
*******************************/
this.initTopSpace = function () {
function adjustTopSpace() {
var height = $( "body > nav" ).height();
var space = height + 50;
$( "body" ).css( "margin-top", "" + space + "px" );
$( "#tree" ).css( "top", "" + space + "px" );
};
$( window ).resize( function () {
adjustTopSpace();
} );
adjustTopSpace();
};
/*******************************
* table view
*******************************/
this.initTableView = function () {
$( "#table td" ).removeAttr( "align" ).removeAttr( "valign" );
};
/*******************************
* extended view
*******************************/
this.initExtendedView = function () {
var $ul = $( "<ul/>" );
// 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 );
$( "<a class='icon'></a>" ).appendTo( $li );
$( "<a class='label' href='" + $label.attr( "href" ) + "'><span class='l10n-columnName'>" + $label.text() + "</span></a>" ).appendTo( $li );
$( "<a class='date' href='" + $date.attr( "href" ) + "'><span class='l10n-columnLastModified'>" + $date.text() + "</span></a>" ).appendTo( $li );
$( "<a class='size' href='" + $size.attr( "href" ) + "'><span class='l10n-columnSize'>" + $size.text() + "</span></a>" ).appendTo( $li );
// header sort icons
var order = document.location.search;
if ( order === "" ) {
order = this.config.defaultSortOrder;
};
var $icon;
if ( order.indexOf( "O=A" ) >= 0 ) {
$icon = $( "<img src='" + this.config.icons.ascending + "' class='sort' alt='ascending' />" );
} else {
$icon = $( "<img src='" + this.config.icons.descending + "' class='sort' alt='descending' />" );
};
if ( order.indexOf( "C=N" ) >= 0 ) {
$li.find( "a.label" ).append( $icon );
} else if ( order.indexOf( "C=M" ) >= 0 ) {
$li.find( "a.date" ).prepend( $icon );
} else if ( order.indexOf( "C=S" ) >= 0 ) {
$li.find( "a.size" ).prepend( $icon );
};
// entries
$( "#table td" ).closest( "tr" ).each( function () {
var path = pathCache.getPathForTableRow( decodeURI( document.location.pathname ), this );
$ul.append( path.updateExtendedHtml() );
} );
$( "#extended" ).append( $ul );
// empty
if ( $ul.children( ".entry:not(.parentfolder)" ).size() === 0 ) {
$( "#extended" ).append( $( "<div class='empty'>empty</div>" ) );
};
// in case of floats
$( "#extended" ).addClass( "clearfix" );
};
/*******************************
* init views
*******************************/
this.initViews = function () {
this.initTableView();
this.initExtendedView();
$( "#viewdetails" ).closest( "li" )
.click( function () {
THIS.applyViewmode( "details" );
} );
$( "#viewicons" ).closest( "li" )
.click( function () {
THIS.applyViewmode( "icons" );
} );
};
/*******************************
* customize
*******************************/
this.customize = function () {
$.ajax( {
url: this.config.customHeader,
dataType: "html",
success: function ( data ) {
$( "#content > header" ).append( $( data ) ).show();
}
} );
$.ajax( {
url: this.config.customFooter,
dataType: "html",
success: function ( data ) {
$( "#content > footer" ).prepend( $( data ) ).show();
}
} );
};
/*******************************
* 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] );
};
};
};
};

31
src/h5ai/js/inc/jquery.json.min.js vendored Normal file
View File

@@ -0,0 +1,31 @@
// v2.2
(function($){$.toJSON=function(o)
{if(typeof(JSON)=='object'&&JSON.stringify)
return JSON.stringify(o);var type=typeof(o);if(o===null)
return"null";if(type=="undefined")
return undefined;if(type=="number"||type=="boolean")
return o+"";if(type=="string")
return $.quoteString(o);if(type=='object')
{if(typeof o.toJSON=="function")
return $.toJSON(o.toJSON());if(o.constructor===Date)
{var month=o.getUTCMonth()+1;if(month<10)month='0'+month;var day=o.getUTCDate();if(day<10)day='0'+day;var year=o.getUTCFullYear();var hours=o.getUTCHours();if(hours<10)hours='0'+hours;var minutes=o.getUTCMinutes();if(minutes<10)minutes='0'+minutes;var seconds=o.getUTCSeconds();if(seconds<10)seconds='0'+seconds;var milli=o.getUTCMilliseconds();if(milli<100)milli='0'+milli;if(milli<10)milli='0'+milli;return'"'+year+'-'+month+'-'+day+'T'+
hours+':'+minutes+':'+seconds+'.'+milli+'Z"';}
if(o.constructor===Array)
{var ret=[];for(var i=0;i<o.length;i++)
ret.push($.toJSON(o[i])||"null");return"["+ret.join(",")+"]";}
var pairs=[];for(var k in o){var name;var type=typeof k;if(type=="number")
name='"'+k+'"';else if(type=="string")
name=$.quoteString(k);else
continue;if(typeof o[k]=="function")
continue;var val=$.toJSON(o[k]);pairs.push(name+":"+val);}
return"{"+pairs.join(", ")+"}";}};$.evalJSON=function(src)
{if(typeof(JSON)=='object'&&JSON.parse)
return JSON.parse(src);return eval("("+src+")");};$.secureEvalJSON=function(src)
{if(typeof(JSON)=='object'&&JSON.parse)
return JSON.parse(src);var filtered=src;filtered=filtered.replace(/\\["\\\/bfnrtu]/g,'@');filtered=filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']');filtered=filtered.replace(/(?:^|:|,)(?:\s*\[)+/g,'');if(/^[\],:{}\s]*$/.test(filtered))
return eval("("+src+")");else
throw new SyntaxError("Error parsing JSON, source is not valid.");};$.quoteString=function(string)
{if(string.match(_escapeable))
{return'"'+string.replace(_escapeable,function(a)
{var c=_meta[a];if(typeof c==='string')return c;c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+(c%16).toString(16);})+'"';}
return'"'+string+'"';};var _escapeable=/["\\\x00-\x1f\x7f-\x9f]/g;var _meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};})(jQuery);

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

@@ -0,0 +1,291 @@
var PathCache = function ( utils ) {
this.cache = {};
this.getPathForFolder = function ( folder ) {
return this.getCachedPath( new Path( utils, folder ) );
};
this.getPathForTableRow = function ( parentFolder, tableRow ) {
return this.getCachedPath( new Path( utils, parentFolder, tableRow ) );
};
this.getCachedPath = function ( path ) {
if ( path.isParentFolder ) {
return path;
};
var cachedPath = this.cache[path.absHref];
if ( cachedPath !== undefined ) {
console.log( "cached path:", cachedPath.absHref );
return cachedPath;
};
console.log( "new path:", path.absHref );
this.cache[path.absHref] = path;
return path;
};
};
var Path = function ( utils, folder, tableRow ) {
var THIS = this;
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 = 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 + "/";
};
};
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 = ( decodeURI( document.location.pathname ) === this.absHref );
if ( this.isParentFolder && h5ai.config.setParentFolderLabels ) {
if ( this.absHref === "/" ) {
this.label = decodeURI( document.domain );
} else {
this.label = utils.splitPathname( utils.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.isEmpty = function() {
if ( this.content === undefined ) {
return true;
};
for ( var prop in this.content ) {
if( this.content.hasOwnProperty( prop ) ) {
return false;
};
};
return true;
};
this.updateHtml = function () {
this.updateCrumbHtml();
this.updateExtendedHtml();
this.updateTreeHtml();
};
this.updateCrumbHtml = function () {
var $html = $( "<li class='crumb' />" ).data( "path", this );
try {
var $a = $( "<a href='" + this.absHref + "'><img src='/h5ai/images/crumb.png' alt='>' />" + this.label + "</a>" );
$html.append( $a );
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 );
};
};
if ( this.isCurrentFolder ) {
$html.addClass( "current" );
};
} 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 {
if ( this.isFolder ) {
$html.addClass( "folder" )
.click( function() {
h5ai.triggerFolderClick( THIS );
} );
} else {
$html.addClass( "file" )
.click( function() {
h5ai.triggerFileClick( THIS );
} );
};
var $a = $( "<a href='" + this.href + "' />" ).appendTo( $html );
$( "<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( " " ).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 {
var $a = $( "<a href='" + this.absHref + "' />" )
.appendTo( $html )
.append( $( "<span class='icon'><img src='" + this.icon16 + "' /></span>" ) )
.append( $( "<span class='label'>" + this.label + "</span>" ) );
if ( this.isFolder ) {
$html.addClass( "folder" );
// 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 {
$indicator.addClass( "open" );
};
$indicator.click( function( event ) {
if ( $indicator.hasClass( "unknown" ) ) {
tree.fetchPath( THIS.absHref, function ( path ) {
$html.replaceWith( path.updateTreeHtml() );
} );
} else if ( $indicator.hasClass( "open" ) ) {
$indicator.removeClass( "open" );
$html.find( "> ul.content" ).slideUp();
} else {
$indicator.addClass( "open" );
$html.find( "> ul.content" ).slideDown();
};
} );
$blank.replaceWith( $indicator );
};
// 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 );
};
};
// 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>" ) );
};
};
} else {
$html.addClass( "file" );
};
} 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;
};
};

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

@@ -0,0 +1,149 @@
var Tree = function ( utils, 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() );
shiftTree();
} );
};
this.fetchTree = function ( pathname, callback, childPath ) {
this.fetchPath( pathname, function ( path ) {
if ( childPath !== undefined ) {
path.content[ childPath.absHref ] = childPath;
};
var parent = utils.splitPathname( pathname )[0];
if ( parent === "" ) {
callback( path );
} else {
THIS.fetchTree( parent, callback, path );
};
} );
};
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 );
}
} );
};
};

15
src/h5ai/js/inc/utils.js Normal file
View File

@@ -0,0 +1,15 @@
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,5 +1,29 @@
( function( $ ) { ( function( $ ) {
// @include "inc/utils.js"
// @include "inc/h5ai.js"
// @include "inc/path.js"
// @include "inc/tree.js"
/*******************************
* create
*******************************/
var utils = new Utils();
var pathCache = new PathCache( utils );
var h5ai = new H5ai( h5aiOptions, h5aiLangs );
var tree = new Tree( utils, h5ai );
/*******************************
* register public api
*******************************/
$.h5ai = {
folderClick: h5ai.folderClick,
fileClick: h5ai.fileClick
};
/******************************* /*******************************
@@ -7,316 +31,8 @@
*******************************/ *******************************/
$( function() { $( function() {
h5ai.init();
$.h5ai = new H5ai(); tree.init();
} ); } );
} )( jQuery );
H5ai = function ( options ) {
/*******************************
* config
*******************************/
var config = {
columnClasses: [ "icon", "name", "date", "size" ],
defaultSortOrder: "C=N;O=A",
viewmodes: [ "details", "icons" ],
store: {
viewmode: "h5ai.viewmode"
},
icons: {
crumb: "/h5ai/images/crumb.png",
ascending: "/h5ai/images/ascending.png",
descending: "/h5ai/images/descending.png"
},
customHeader: "h5ai.header.html",
customFooter: "h5ai.footer.html",
callbacks: {
folderClick: [],
fileClick: []
}
};
/*******************************
* public api
*******************************/
this.folderClick = function ( fn ) {
if ( typeof fn === "function" ) {
config.callbacks.folderClick.push( fn );
};
return this;
};
this.fileClick = function ( fn ) {
if ( typeof fn === "function" ) {
config.callbacks.fileClick.push( fn );
};
return this;
};
/*******************************
* init (will be called at the bottom)
*******************************/
var init = function () {
applyViewmode();
initBreadcrumb();
initViews();
customize();
};
/*******************************
* callback triggers
*******************************/
var triggerFolderClick = function ( label ) {
for ( idx in config.callbacks.folderClick ) {
config.callbacks.folderClick[idx].call( window, label );
};
};
var triggerFileClick = function ( label ) {
for ( idx in config.callbacks.fileClick ) {
config.callbacks.fileClick[idx].call( window, label );
};
};
/*******************************
* local stored viewmode
*******************************/
var getViewmode = function () {
var viewmode = localStorage.getItem( config.store.viewmode );
if ( $.inArray( viewmode, config.viewmodes ) ) {
return viewmode;
};
return config.viewmodes[0];
};
var applyViewmode = function ( viewmode ) {
$( "#table" ).hide();
if ( viewmode !== undefined ) {
localStorage.setItem( config.store.viewmode, viewmode );
};
if ( getViewmode() === "icons" ) {
$( "#extended" ).removeClass( "details-view" ).addClass( "icons-view" ).show();
} else {
$( "#extended" ).addClass( "details-view" ).removeClass( "icons-view" ).show();
};
};
/*******************************
* breadcrumb and doc title
*******************************/
var initBreadcrumb = function () {
$( "#domain span" ).text( document.domain );
var pathname = decodeURI( document.location.pathname );
var parts = pathname.split( "/" );
var path = "/";
var $ul = $( "nav ul" );
for ( idx in parts ) {
var part = parts[idx];
if ( part !== "" ) {
path += part + "/";
$ul.append( $( "<li class='crumb'><a href='" + path + "'><img src='" + config.icons.crumb + "' alt='>' />" + part + "</a></li>" ) );
};
};
document.title = document.domain + pathname;
};
/*******************************
* table view
*******************************/
var 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 tr" ).each( function () {
var colIdx = 0;
$( this ).find( "th,td" ).each( function () {
$( this ).addClass( getColumnClass( colIdx++ ) );
} );
} );
};
/*******************************
* extended view
*******************************/
var initExtendedView = function () {
var $ul = $( "<ul/>" );
// headers
var $li = $( "<li class='header' />" ).appendTo( $ul );
$( "<a class='icon'></a>" ).appendTo( $li );
var $label = $( "th.name a" );
var $date = $( "th.date a" );
var $size = $( "th.size a" );
$( "<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
var order = document.location.search;
if ( order === "" ) {
order = config.defaultSortOrder;
};
var $icon;
if ( order.indexOf( "O=A" ) >= 0 ) {
$icon = $( "<img src='" + config.icons.ascending + "' class='sort' alt='ascending' />" );
} else {
$icon = $( "<img src='" + config.icons.descending + "' class='sort' alt='descending' />" );
};
if ( order.indexOf( "C=N" ) >= 0 ) {
$li.find( "a.label" ).append( $icon );
} else if ( order.indexOf( "C=M" ) >= 0 ) {
$li.find( "a.date" ).prepend( $icon );
} else if ( order.indexOf( "C=S" ) >= 0 ) {
$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 );
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 );
// empty
$entries = $( "#extended .entry" );
if ( $entries.size() === 0 || $entries.size() === 1 && $entries.find( ".label" ).text() === "Parent Directory" ) {
$( "#extended" ).append( $( "<div class='empty'>empty</div>" ) );
};
// in case of floats
$( "#extended" ).append( $( "<div class='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
*******************************/
var initViews = function () {
initTableView();
initExtendedView();
$( "#viewdetails" ).closest( "li" )
.click( function () {
applyViewmode( "details" );
} );
$( "#viewicons" ).closest( "li" )
.click( function () {
applyViewmode( "icons" );
} );
};
/*******************************
* customize
*******************************/
var customize = function () {
$.ajax( {
url: config.customHeader,
dataType: "html",
success: function ( data ) {
$( "#content > header" ).append( $( data ) ).show();
}
} );
$.ajax( {
url: config.customFooter,
dataType: "html",
success: function ( data ) {
$( "#content > footer" ).prepend( $( data ) ).show();
}
} );
};
/*******************************
* finally run init
*******************************/
init();
};
} )( jQuery );

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

@@ -0,0 +1,91 @@
/*
* 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
};
/*
* 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"
}
};

View File

@@ -1,5 +1,5 @@
################################ ################################
# h5ai 0.4 # h5ai 0.8
# customized .htaccess # customized .htaccess
################################ ################################
@@ -8,14 +8,16 @@
# Options +FollowSymLinks # Options +FollowSymLinks
################################
# cache images for 52 weeks
################################
<IfModule mod_headers.c> <IfModule mod_headers.c>
################################
# cache images for 52 weeks
################################
<FilesMatch "\.png$"> <FilesMatch "\.png$">
Header set Cache-Control "max-age=31449600, public" Header set Cache-Control "max-age=31449600, public"
</FilesMatch> </FilesMatch>
</IfModule> </IfModule>
@@ -54,6 +56,7 @@
IndexOrderDefault Ascending Name IndexOrderDefault Ascending Name
IndexOptions Type=text/html;h5ai=0.8
IndexOptions Charset=UTF-8 IndexOptions Charset=UTF-8
IndexOptions FancyIndexing IndexOptions FancyIndexing
IndexOptions HTMLTable IndexOptions HTMLTable
@@ -87,9 +90,9 @@
AddIcon /h5ai/icons/16x16/makefile.png .pom pom.xml build.xml AddIcon /h5ai/icons/16x16/makefile.png .pom pom.xml build.xml
AddIcon /h5ai/icons/16x16/bin.png .so .o AddIcon /h5ai/icons/16x16/bin.png .so .o
AddIcon /h5ai/icons/16x16/zip.png .zip .Z .z .jar .war
AddIcon /h5ai/icons/16x16/tar.png .tar
AddIcon /h5ai/icons/16x16/archive.png .tar.gz .tgz .tar.bz2 AddIcon /h5ai/icons/16x16/archive.png .tar.gz .tgz .tar.bz2
AddIcon /h5ai/icons/16x16/zip.png .zip .Z .z .jar .war .gz .bz2
AddIcon /h5ai/icons/16x16/tar.png .tar
AddIcon /h5ai/icons/16x16/pdf.png .pdf AddIcon /h5ai/icons/16x16/pdf.png .pdf
AddIcon /h5ai/icons/16x16/deb.png .deb AddIcon /h5ai/icons/16x16/deb.png .deb
AddIcon /h5ai/icons/16x16/rpm.png .rpm AddIcon /h5ai/icons/16x16/rpm.png .rpm

File diff suppressed because one or more lines are too long

View File

@@ -3,6 +3,7 @@
<section id="extended"></section> <section id="extended"></section>
<footer></footer> <footer></footer>
</section> </section>
<section id="tree"></section>
<footer> <footer>
<a id="html5" href="http://www.w3.org/html/logo/" target="_blank" title="HTML5 semantics, storage & CSS3"> <a id="html5" href="http://www.w3.org/html/logo/" target="_blank" title="HTML5 semantics, storage & CSS3">
<img class="logo" src="/h5ai/images/html5.png" alt="html5" /> <img class="logo" src="/h5ai/images/html5.png" alt="html5" />
@@ -10,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.4">h5ai</a> <a href="http://larsjung.de/h5ai" target="_blank" title="h5ai 0.8">h5ai</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.4"> <meta name="h5ai-version" content="h5ai 0.8">
<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">
@@ -16,9 +16,15 @@
<nav> <nav>
<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="domain" class="crumb">
<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/home.png" alt="domain" /><span>domain</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="viewicons" class="view">
<a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" /><span class="l10n-viewIcons">icons</span></a>
</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> <div class="clearfix"></div>
</nav> </nav>

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

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: 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.

After

Width:  |  Height:  |  Size: 649 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 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

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

@@ -0,0 +1,91 @@
/*
* h5ai 0.8
* 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
};
/*
* 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"
}
};