Added PHP implementation. For a full list of changes see README.md.
44
README.md
|
@ -9,17 +9,31 @@ It uses the [Faenza icon set](http://tiheum.deviantart.com/art/Faenza-Icons-1733
|
|||
|
||||
## Changelog
|
||||
|
||||
#### v0.12.3 · *2011-07-30*
|
||||
### v0.13 · *2011-08-06*
|
||||
|
||||
* added tr translation by [Batuhan Icoz](http://github.com/batuhanicoz/h5ai)
|
||||
* added PHP implementation! (should work with PHP 5.2+)
|
||||
* added new options
|
||||
* changed layout of the bottom bar to display status information
|
||||
* added language selector to the bottom bar
|
||||
* quoted keys in `options.js` to make it valid json
|
||||
* changed value of option `lang` from `undefined` to `null`
|
||||
* added some new keys to `h5aiLangs`
|
||||
* added browser caching rules for css and js
|
||||
* added pt translation by [Jonnathan](http://github.com/jonnsl)
|
||||
* added bg translation by George Andonov
|
||||
|
||||
|
||||
#### v0.12.2 · *2011-07-30*
|
||||
### v0.12.3 · *2011-07-30*
|
||||
|
||||
* added tr translation by [Batuhan Icoz](http://github.com/batuhanicoz)
|
||||
|
||||
|
||||
### v0.12.2 · *2011-07-30*
|
||||
|
||||
* added es translation by Jose David Calderon Serrano
|
||||
|
||||
|
||||
#### v0.12.1 · *2011-07-29*
|
||||
### v0.12.1 · *2011-07-29*
|
||||
|
||||
* fixed unchecked use of console.log
|
||||
|
||||
|
@ -34,12 +48,12 @@ It uses the [Faenza icon set](http://tiheum.deviantart.com/art/Faenza-Icons-1733
|
|||
* changed license to MIT license, see `LICENSE.txt`
|
||||
|
||||
|
||||
#### v0.10.2 · *2011-07-26*
|
||||
### v0.10.2 · *2011-07-26*
|
||||
|
||||
* improved tree scrollbar
|
||||
|
||||
|
||||
#### v0.10.1 · *2011-07-24*
|
||||
### v0.10.1 · *2011-07-24*
|
||||
|
||||
* fixed problems with ' in links
|
||||
|
||||
|
@ -85,7 +99,7 @@ It uses the [Faenza icon set](http://tiheum.deviantart.com/art/Faenza-Icons-1733
|
|||
* added localization, see `options.js`
|
||||
|
||||
|
||||
#### v0.5.3 · *2011-07-04*
|
||||
### v0.5.3 · *2011-07-04*
|
||||
|
||||
* refactored js
|
||||
* added basic options support via `options.js`
|
||||
|
@ -93,13 +107,13 @@ It uses the [Faenza icon set](http://tiheum.deviantart.com/art/Faenza-Icons-1733
|
|||
* optional tree sidebar
|
||||
|
||||
|
||||
#### v0.5.2 · *2011-07-02*
|
||||
### v0.5.2 · *2011-07-02*
|
||||
|
||||
* details view adjusts to window width
|
||||
* linked icon for *.gz and *.bz2
|
||||
|
||||
|
||||
#### v0.5.1 · *2011-07-01*
|
||||
### v0.5.1 · *2011-07-01*
|
||||
|
||||
* disabled tree sidebar for now, since it had unwanted side effects
|
||||
|
||||
|
@ -119,13 +133,13 @@ It uses the [Faenza icon set](http://tiheum.deviantart.com/art/Faenza-Icons-1733
|
|||
* updated dot.access
|
||||
|
||||
|
||||
#### v0.3.2 · *2011-06-24*
|
||||
### v0.3.2 · *2011-06-24*
|
||||
|
||||
* removed lib versions from file names
|
||||
* added 'empty' indicator for icons view
|
||||
|
||||
|
||||
#### v0.3.1 · *2011-06-24*
|
||||
### v0.3.1 · *2011-06-24*
|
||||
|
||||
* refactored js
|
||||
* added `folderClick` and `fileClick` callback hooks
|
||||
|
@ -140,20 +154,20 @@ It uses the [Faenza icon set](http://tiheum.deviantart.com/art/Faenza-Icons-1733
|
|||
* updated jQuery to version 1.6.1
|
||||
|
||||
|
||||
#### v0.2.3 · *2011-06-17*
|
||||
### v0.2.3 · *2011-06-17*
|
||||
|
||||
* more refactoring in main.js
|
||||
* ~~added custom js support, and global includes~~ *removed, only custom top and bottom sections supported*
|
||||
|
||||
|
||||
#### v0.2.2 · *2011-06-16*
|
||||
### v0.2.2 · *2011-06-16*
|
||||
|
||||
* refactored a lot, added some comments
|
||||
* included fixes from [NumEricR](http://github.com/NumEricR/h5ai)
|
||||
* included fixes from [NumEricR](http://github.com/NumEricR)
|
||||
* added top/bottom message support, only basicly styled
|
||||
|
||||
|
||||
#### v0.2.1 · *2011-06-16*
|
||||
### v0.2.1 · *2011-06-16*
|
||||
|
||||
* fixed croped filenames
|
||||
* fixed missing .png extension in header
|
||||
|
|
|
@ -3,7 +3,7 @@ custom = true
|
|||
|
||||
# project
|
||||
project.name = h5ai
|
||||
project.version = 0.12.3
|
||||
project.version = 0.13
|
||||
|
||||
|
||||
# src
|
||||
|
|
BIN
release/h5ai-0.13.tar.gz
Normal file
16
src/h5ai/.htaccess
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
AddType text/html .php
|
||||
|
||||
# cache images, css and js for 52 weeks
|
||||
<IfModule headers_module>
|
||||
<FilesMatch "\.png$">
|
||||
Header set Cache-Control "max-age=31449600, public"
|
||||
</FilesMatch>
|
||||
<FilesMatch "\.css$">
|
||||
Header set Cache-Control "max-age=31449600, public"
|
||||
</FilesMatch>
|
||||
<FilesMatch "\.js$">
|
||||
Header set Cache-Control "max-age=31449600, public"
|
||||
</FilesMatch>
|
||||
</IfModule>
|
||||
|
7
src/h5ai/cache/readme.md
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Cache
|
||||
|
||||
This directory is used for server side caching. To use caching make this
|
||||
directory writable for Apache.
|
||||
|
||||
There is no critical data in here. You can savely remove any content. This
|
||||
will clear the cache.
|
|
@ -64,6 +64,16 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
&.folder-parent {
|
||||
.date, .size {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
&.folder {
|
||||
.size {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.icon, .label, .date, .size {
|
||||
padding: 6px;
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
|
||||
@import "inc/html5reset";
|
||||
@import "inc/mixins";
|
||||
@import "html5reset";
|
||||
@import "mixins";
|
||||
|
||||
|
||||
html.js {
|
||||
.jsDisabledFallback {
|
||||
.hideOnJs {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
html.no-js {
|
||||
body > nav ul {
|
||||
.hideOnNoJs {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
@ -109,9 +109,9 @@ body > nav {
|
|||
}
|
||||
|
||||
|
||||
@import "inc/table";
|
||||
@import "inc/extended";
|
||||
@import "inc/tree";
|
||||
@import "table";
|
||||
@import "extended";
|
||||
@import "tree";
|
||||
|
||||
|
||||
body > footer {
|
||||
|
@ -120,7 +120,7 @@ body > footer {
|
|||
width: 100%;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 10px 0;
|
||||
padding: 6px 0 8px 0;
|
||||
background-color: rgb(241,241,241);
|
||||
border-top: 2px solid rgb(210,210,210);
|
||||
|
||||
|
@ -132,27 +132,63 @@ body > footer {
|
|||
color: #555;
|
||||
text-decoration: none;
|
||||
.transition( all 0.2s ease-in-out );
|
||||
|
||||
opacity: 0.7;
|
||||
|
||||
&:hover {
|
||||
color: #e80;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.left {
|
||||
display: block;
|
||||
padding: 0 8px;
|
||||
float: left
|
||||
}
|
||||
.center {
|
||||
display: block;
|
||||
margin: 0 300px;
|
||||
}
|
||||
.right {
|
||||
display: block;
|
||||
padding: 0 8px;
|
||||
float: right
|
||||
}
|
||||
#langSelector {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
.langOptions {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
display: none;
|
||||
right: 0;
|
||||
top: 0;
|
||||
background-color: rgb(241,241,241);
|
||||
border: 1px solid rgb(210,210,210);
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
text-align: left;
|
||||
|
||||
li {
|
||||
padding: 8px 24px 10px 24px;
|
||||
white-space: nowrap;
|
||||
border-top: 1px solid rgb(231,231,231);
|
||||
.transition( all 0.2s ease-in-out );
|
||||
|
||||
&.current {
|
||||
color: #333;
|
||||
background-color: rgba(255,255,255,0.8);
|
||||
}
|
||||
&:hover {
|
||||
color: #e80;
|
||||
background-color: rgba(255,255,255,0.8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#html5 {
|
||||
position: absolute;
|
||||
left: 6px;
|
||||
bottom: 6px;
|
||||
opacity: 0.4;
|
||||
.transition( all 0.2s ease-in-out );
|
||||
|
||||
img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
|
||||
#tree {
|
||||
position: fixed;
|
||||
display: none;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
top: 82px;
|
||||
z-index: 1;
|
||||
overflow: auto;
|
||||
font-size: 0.85em;
|
||||
padding: 16px 16px 16px 16px;
|
||||
|
|
3
src/h5ai/css/main-js.less
Normal file
|
@ -0,0 +1,3 @@
|
|||
|
||||
@import "inc/main";
|
||||
|
15
src/h5ai/css/main-php.less
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
@import "inc/main";
|
||||
|
||||
|
||||
#table {
|
||||
display: none;
|
||||
}
|
||||
#tree, #content > header, #content > footer {
|
||||
display: block;
|
||||
}
|
||||
html.no-js {
|
||||
#extended.details-view, #extended.icons-view {
|
||||
display: block;
|
||||
}
|
||||
}
|
|
@ -4,20 +4,27 @@
|
|||
<footer></footer>
|
||||
</section>
|
||||
<section id="tree"></section>
|
||||
<footer>
|
||||
<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="techclass" src="/h5ai/images/html5-semantics.png" alt="html5-semantics" />
|
||||
<img class="techclass" src="/h5ai/images/html5-storage.png" alt="html5-storage" />
|
||||
<img class="techclass" src="/h5ai/images/html5-css3.png" alt="html5-css3" />
|
||||
</a>
|
||||
<a href="http://larsjung.de/h5ai" target="_blank" title="h5ai project page">h5ai %BUILD_VERSION%</a>
|
||||
<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>
|
||||
<footer class="clearfix">
|
||||
<span class="left">
|
||||
<a href="http://larsjung.de/h5ai" target="_blank" title="h5ai project page">h5ai %BUILD_VERSION% (js)</a>
|
||||
</span>
|
||||
<span class="right">
|
||||
<span class="hideOnJs">JavaScript is disabled!</span>
|
||||
<span id="langSelector">
|
||||
<span class="lang">en</span> - <span class="l10n-lang">english</span>
|
||||
<span class="langOptions"></span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="center">
|
||||
<span class="hideOnNoJs">
|
||||
<span class="folderCount"></span> <span class="l10n-folders">folders</span>
|
||||
·
|
||||
<span class="fileCount"></span> <span class="l10n-files">files</span>
|
||||
</span>
|
||||
</span>
|
||||
</footer>
|
||||
<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 src="/h5ai/js/lib/jquery.min.js"></script>
|
||||
<script src="/h5ai/options.js"></script>
|
||||
<script src="/h5ai/js/main.js"></script>
|
||||
<script src="/h5ai/js/main-js.js"></script>
|
||||
</body>
|
||||
</html>
|
4
src/h5ai/footer.php
Normal file
|
@ -0,0 +1,4 @@
|
|||
<!-- generated code ends here -->
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
|
@ -3,30 +3,29 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Directory index · styled with h5ai</title>
|
||||
<meta name="h5ai-version" content="h5ai %BUILD_VERSION%">
|
||||
<meta name="h5ai-version" content="h5ai %BUILD_VERSION% (js)">
|
||||
<meta name="description" content="Directory index styled with h5ai (http://larsjung.de/h5ai)">
|
||||
<meta name="keywords" content="directory, index, autoindex, h5ai">
|
||||
<link rel="shortcut icon" type="image/png" href="/h5ai/images/h5ai-16x16.png">
|
||||
<link rel="apple-touch-icon" type="image/png" href="/h5ai/images/h5ai-48x48.png">
|
||||
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Ubuntu:regular,italic,bold">
|
||||
<link rel="stylesheet" type="text/css" href="/h5ai/css/main.css">
|
||||
<link rel="stylesheet" type="text/css" href="/h5ai/css/main-js.css">
|
||||
<script src="/h5ai/js/lib/modernizr.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="clearfix">
|
||||
<span class="jsDisabledFallback">Directory index · JavaScript is disabled</span>
|
||||
<ul>
|
||||
<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 id="viewicons" class="view hideOnNoJs">
|
||||
<a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" /><span class="l10n-icons">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 id="viewdetails" class="view hideOnNoJs" >
|
||||
<a href="#"><img src="/h5ai/images/view-details.png" alt="view-details" /><span class="l10n-details">details</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<section id="content">
|
||||
<header></header>
|
||||
<section id="table" class="jsDisabledFallback">
|
||||
<section id="table" class="hideOnJs">
|
||||
<!--
|
||||
The following code was generated by apache's autoindex module. It is not valid HTML 5 for the
|
||||
reason, that 'align' and 'valign' attributes on the td element are obsolete. Both of them are
|
||||
|
|
55
src/h5ai/header.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="no-js">
|
||||
<?php include "php/main.php"; ?>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title><?php echo $h5ai->getTitle(); ?></title>
|
||||
<meta name="h5ai-version" content="h5ai %BUILD_VERSION% (php)">
|
||||
<meta name="description" content="Directory index styled with h5ai (http://larsjung.de/h5ai)">
|
||||
<meta name="keywords" content="directory, index, autoindex, h5ai">
|
||||
<link rel="shortcut icon" type="image/png" href="/h5ai/images/h5ai-16x16.png">
|
||||
<link rel="apple-touch-icon" type="image/png" href="/h5ai/images/h5ai-48x48.png">
|
||||
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Ubuntu:regular,italic,bold">
|
||||
<link rel="stylesheet" type="text/css" href="/h5ai/css/main-php.css">
|
||||
<script src="/h5ai/js/lib/modernizr.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="clearfix">
|
||||
<ul>
|
||||
<?php echo $crumb->toHtml(); ?>
|
||||
<li id="viewicons" class="view hideOnNoJs">
|
||||
<a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" /><span class="l10n-icons">icons</span></a>
|
||||
</li>
|
||||
<li id="viewdetails" class="view hideOnNoJs" >
|
||||
<a href="#"><img src="/h5ai/images/view-details.png" alt="view-details" /><span class="l10n-details">details</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<?php echo $tree->toHtml(); ?>
|
||||
<section id="content">
|
||||
<?php echo $customize->getHeader(); ?>
|
||||
<?php echo $extended->toHtml(); ?>
|
||||
<?php echo $customize->getFooter(); ?>
|
||||
</section>
|
||||
<footer class="clearfix">
|
||||
<span class="left">
|
||||
<a href="http://larsjung.de/h5ai" target="_blank" title="h5ai project page">h5ai %BUILD_VERSION% (php)</a>
|
||||
</span>
|
||||
<span class="right">
|
||||
<span class="hideOnJs">JavaScript is disabled!</span>
|
||||
<span id="langSelector">
|
||||
<span class="lang">en</span> - <span class="l10n-lang">english</span>
|
||||
<span class="langOptions"></span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="center">
|
||||
<?php echo $extended->getFolderCount(); ?> <span class="l10n-folders">folders</span>
|
||||
·
|
||||
<?php echo $extended->getFileCount(); ?> <span class="l10n-files">files</span>
|
||||
</span>
|
||||
</footer>
|
||||
<script src="/h5ai/js/lib/jquery.min.js"></script>
|
||||
<script src="/h5ai/options.js"></script>
|
||||
<script src="/h5ai/js/main-php.js"></script>
|
||||
<section id="table">
|
||||
<!-- the following code was generated by apache's autoindex module and gets ignored -->
|
Before Width: | Height: | Size: 494 B After Width: | Height: | Size: 494 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 424 B |
Before Width: | Height: | Size: 428 B |
Before Width: | Height: | Size: 535 B |
Before Width: | Height: | Size: 811 B |
155
src/h5ai/js/inc/extended.js
Normal file
|
@ -0,0 +1,155 @@
|
|||
|
||||
var Extended = function ( pathCache ) {
|
||||
|
||||
|
||||
/*******************************
|
||||
* config
|
||||
*******************************/
|
||||
|
||||
this.config = {
|
||||
defaultSortOrder: "C=N;O=A",
|
||||
customHeader: "h5ai.header.html",
|
||||
customFooter: "h5ai.footer.html"
|
||||
};
|
||||
|
||||
|
||||
/*******************************
|
||||
* init
|
||||
*******************************/
|
||||
|
||||
this.init = function () {
|
||||
|
||||
try {
|
||||
document.title = decodeURI( document.domain + document.location.pathname );
|
||||
} catch ( err ) {
|
||||
document.title = document.domain + document.location.pathname;
|
||||
};
|
||||
|
||||
this.initBreadcrumb();
|
||||
this.initExtendedView();
|
||||
this.customize();
|
||||
this.initCounts();
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*******************************
|
||||
* breadcrumb
|
||||
*******************************/
|
||||
|
||||
this.initBreadcrumb = function () {
|
||||
|
||||
var $ul = $( "body > nav ul" );
|
||||
|
||||
var pathname = "/";
|
||||
var path = pathCache.getPathForFolder( pathname );
|
||||
$ul.append( path.updateCrumbHtml() );
|
||||
|
||||
var pathnameParts = document.location.pathname.split( "/" );
|
||||
for ( idx in pathnameParts ) {
|
||||
var part = pathnameParts[idx];
|
||||
if ( part !== "" ) {
|
||||
pathname += part + "/";
|
||||
var path = pathCache.getPathForFolder( pathname );
|
||||
$ul.append( path.updateCrumbHtml() );
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*******************************
|
||||
* 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-name'>" + $label.text() + "</span></a>" ).appendTo( $li );
|
||||
$( "<a class='date' href='" + $date.attr( "href" ) + "'><span class='l10n-lastModified'>" + $date.text() + "</span></a>" ).appendTo( $li );
|
||||
$( "<a class='size' href='" + $size.attr( "href" ) + "'><span class='l10n-size'>" + $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='/h5ai/images/ascending.png' class='sort' alt='ascending' />" );
|
||||
} else {
|
||||
$icon = $( "<img src='/h5ai/images/descending.png' 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 );
|
||||
};
|
||||
|
||||
$.timer.log( "start entries" );
|
||||
// entries
|
||||
$( "#table td" ).closest( "tr" ).each( function () {
|
||||
var path = pathCache.getPathForTableRow( document.location.pathname, this );
|
||||
$ul.append( path.updateExtendedHtml() );
|
||||
} );
|
||||
$.timer.log( "end entries" );
|
||||
|
||||
$( "#extended" ).append( $ul );
|
||||
$.log( document.location.pathname, "folders:", $( "#extended .folder" ).size() , "files:", $( "#extended .file" ).size() );
|
||||
|
||||
// empty
|
||||
if ( $ul.children( ".entry:not(.parentfolder)" ).size() === 0 ) {
|
||||
$( "#extended" ).append( $( "<div class='empty l10n-empty'>empty</div>" ) );
|
||||
};
|
||||
|
||||
// in case of floats
|
||||
$( "#extended" ).addClass( "clearfix" );
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*******************************
|
||||
* 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();
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*******************************
|
||||
* init counts
|
||||
*******************************/
|
||||
|
||||
this.initCounts = function () {
|
||||
|
||||
$( ".folderCount" ).text( $( "#extended .entry.folder:not(.parentfolder)" ).size() );
|
||||
$( ".fileCount" ).text( $( "#extended .entry.file" ).size() );
|
||||
};
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
var H5ai = function ( options, langs, pathCache ) {
|
||||
var H5ai = function ( options, langs ) {
|
||||
|
||||
|
||||
/*******************************
|
||||
|
@ -7,28 +7,27 @@ var H5ai = function ( options, langs, pathCache ) {
|
|||
*******************************/
|
||||
|
||||
var defaults = {
|
||||
defaultSortOrder: "C=N;O=A",
|
||||
store: {
|
||||
viewmode: "h5ai.viewmode"
|
||||
viewmode: "h5ai.viewmode",
|
||||
lang: "h5ai.lang"
|
||||
},
|
||||
customHeader: "h5ai.header.html",
|
||||
customFooter: "h5ai.footer.html",
|
||||
callbacks: {
|
||||
pathClick: []
|
||||
},
|
||||
|
||||
viewmodes: [ "details", "icons" ],
|
||||
showTree: false,
|
||||
showTree: true,
|
||||
folderStatus: {
|
||||
},
|
||||
lang: undefined,
|
||||
lang: null,
|
||||
useBrowserLang: true,
|
||||
setParentFolderLabels: true,
|
||||
linkHoverStates: true
|
||||
};
|
||||
this.config = $.extend( {}, defaults, options );
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************************
|
||||
* public api
|
||||
*******************************/
|
||||
|
@ -49,14 +48,14 @@ var H5ai = function ( options, langs, pathCache ) {
|
|||
|
||||
this.init = function () {
|
||||
|
||||
document.title = decodeURI( document.domain + document.location.pathname );
|
||||
|
||||
this.applyViewmode();
|
||||
this.initBreadcrumb();
|
||||
this.initTopSpace();
|
||||
this.initViews();
|
||||
this.customize();
|
||||
this.initTree();
|
||||
this.linkHoverStates();
|
||||
this.initLangSelector( langs );
|
||||
this.localize( langs, this.config.lang, this.config.useBrowserLang );
|
||||
this.initIndicators();
|
||||
};
|
||||
|
||||
|
||||
|
@ -93,7 +92,7 @@ var H5ai = function ( options, langs, pathCache ) {
|
|||
viewmode = this.getViewmode();
|
||||
|
||||
$( "#viewdetails,#viewicons" ).hide().removeClass( "current" );
|
||||
|
||||
|
||||
if ( this.config.viewmodes.length > 1 ) {
|
||||
if ( $.inArray( "details", this.config.viewmodes ) >= 0 ) {
|
||||
$( "#viewdetails" ).show();
|
||||
|
@ -116,31 +115,6 @@ var H5ai = function ( options, langs, pathCache ) {
|
|||
|
||||
|
||||
|
||||
/*******************************
|
||||
* breadcrumb
|
||||
*******************************/
|
||||
|
||||
this.initBreadcrumb = function () {
|
||||
|
||||
var $ul = $( "body > nav ul" );
|
||||
|
||||
var pathname = "/";
|
||||
var path = pathCache.getPathForFolder( pathname );
|
||||
$ul.append( path.updateCrumbHtml() );
|
||||
|
||||
var pathnameParts = document.location.pathname.split( "/" );
|
||||
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
|
||||
*******************************/
|
||||
|
@ -175,74 +149,13 @@ var H5ai = function ( options, langs, pathCache ) {
|
|||
|
||||
|
||||
|
||||
/*******************************
|
||||
* 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='/h5ai/images/ascending.png' class='sort' alt='ascending' />" );
|
||||
} else {
|
||||
$icon = $( "<img src='/h5ai/images/descending.png' 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 );
|
||||
};
|
||||
|
||||
$.timer.log( "start entries" );
|
||||
// entries
|
||||
$( "#table td" ).closest( "tr" ).each( function () {
|
||||
var path = pathCache.getPathForTableRow( document.location.pathname, this );
|
||||
$ul.append( path.updateExtendedHtml() );
|
||||
} );
|
||||
$.timer.log( "end entries" );
|
||||
$( "#table" ).remove();
|
||||
|
||||
$( "#extended" ).append( $ul );
|
||||
$.log( document.location.pathname, "folders:", $( "#extended .folder" ).size() , "files:", $( "#extended .file" ).size() );
|
||||
|
||||
// empty
|
||||
if ( $ul.children( ".entry:not(.parentfolder)" ).size() === 0 ) {
|
||||
$( "#extended" ).append( $( "<div class='empty l10n-empty'>empty</div>" ) );
|
||||
};
|
||||
|
||||
// in case of floats
|
||||
$( "#extended" ).addClass( "clearfix" );
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*******************************
|
||||
* init views
|
||||
*******************************/
|
||||
|
||||
this.initViews = function () {
|
||||
|
||||
this.initExtendedView();
|
||||
$( "#table" ).remove();
|
||||
|
||||
$( "#viewdetails" ).closest( "li" )
|
||||
.click( $.proxy( function () {
|
||||
|
@ -257,25 +170,61 @@ var H5ai = function ( options, langs, pathCache ) {
|
|||
|
||||
|
||||
/*******************************
|
||||
* customize
|
||||
* init tree
|
||||
*******************************/
|
||||
|
||||
this.customize = function () {
|
||||
this.initTree = function () {
|
||||
|
||||
$.ajax( {
|
||||
url: this.config.customHeader,
|
||||
dataType: "html",
|
||||
success: function ( data ) {
|
||||
$( "#content > header" ).append( $( data ) ).show();
|
||||
}
|
||||
var $tree = $( "#tree" );
|
||||
var $extended = $( "#extended" );
|
||||
var shiftTree = function ( forceVisible, dontAnimate ) {
|
||||
if ( $tree.outerWidth() < $extended.offset().left || forceVisible === true ) {
|
||||
if ( dontAnimate === true ) {
|
||||
$tree.stop().css( { left: 0 } );
|
||||
} else {
|
||||
$tree.stop().animate( { left: 0 } );
|
||||
};
|
||||
} else {
|
||||
if ( dontAnimate === true ) {
|
||||
$tree.stop().css( { left: 18 - $tree.outerWidth() } );
|
||||
} else {
|
||||
$tree.stop().animate( { left: 18 - $tree.outerWidth() } );
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
$tree.hover( function () { shiftTree( true ); }, function () { shiftTree(); } );
|
||||
$( window ).resize( function() {
|
||||
shiftTree();
|
||||
} );
|
||||
|
||||
$.ajax( {
|
||||
url: this.config.customFooter,
|
||||
dataType: "html",
|
||||
success: function ( data ) {
|
||||
$( "#content > footer" ).prepend( $( data ) ).show();
|
||||
}
|
||||
shiftTree( false, true );
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*******************************
|
||||
* link hover states
|
||||
*******************************/
|
||||
|
||||
this.linkHoverStates = function () {
|
||||
|
||||
if ( !this.config.linkHoverStates ) {
|
||||
return;
|
||||
};
|
||||
|
||||
$( "a[href^='/']:not(.linkedHoverStates)" ).each( function () {
|
||||
|
||||
var $a = $( this ).addClass( "linkedHoverStates" );
|
||||
var href = $a.attr( "href" );
|
||||
$a.hover(
|
||||
function () {
|
||||
$( "a[href='" + href + "']" ).addClass( "hover" );
|
||||
},
|
||||
function () {
|
||||
$( "a[href='" + href + "']" ).removeClass( "hover" );
|
||||
}
|
||||
);
|
||||
} );
|
||||
};
|
||||
|
||||
|
@ -285,22 +234,111 @@ var H5ai = function ( options, langs, pathCache ) {
|
|||
* localization
|
||||
*******************************/
|
||||
|
||||
this.localize = function ( data, lang, useBrowserLang ) {
|
||||
this.initLangSelector = function ( langs ) {
|
||||
|
||||
var sortedLangsKeys = [];
|
||||
for ( lang in langs ) {
|
||||
sortedLangsKeys.push( lang );
|
||||
};
|
||||
sortedLangsKeys.sort();
|
||||
|
||||
var THIS = this;
|
||||
var $ul = $( "<ul />" );
|
||||
for ( idx in sortedLangsKeys ) {
|
||||
( function ( lang ) {
|
||||
$( "<li class='langOption' />" )
|
||||
.addClass( lang )
|
||||
.text( lang + " - " + langs[lang]["lang"] )
|
||||
.appendTo( $ul )
|
||||
.click( function () {
|
||||
localStorage.setItem( THIS.config.store.lang, lang );
|
||||
THIS.localize( langs, lang, false );
|
||||
} );
|
||||
} )( sortedLangsKeys[idx] );
|
||||
};
|
||||
$( "#langSelector .langOptions" )
|
||||
.append( $ul );
|
||||
$( "#langSelector" ).hover(
|
||||
function () {
|
||||
var $ele = $( ".langOptions" );
|
||||
$ele.css( "top", "-" + $ele.outerHeight() + "px" ).stop( true, true ).fadeIn();
|
||||
},
|
||||
function () {
|
||||
$( ".langOptions" ).stop( true, true ).fadeOut();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.localize = function ( langs, lang, useBrowserLang ) {
|
||||
|
||||
if ( useBrowserLang === true ) {
|
||||
var browserLang = navigator.language;
|
||||
if ( data[ browserLang ] !== undefined ) {
|
||||
if ( langs[ browserLang ] !== undefined ) {
|
||||
lang = browserLang;
|
||||
} else if ( browserLang.length > 2 && data[ browserLang.substr( 0, 2 ) ] !== undefined ) {
|
||||
} else if ( browserLang.length > 2 && langs[ browserLang.substr( 0, 2 ) ] !== undefined ) {
|
||||
lang = browserLang.substr( 0, 2 );
|
||||
};
|
||||
};
|
||||
|
||||
if ( lang !== "en" && data[ lang ] !== undefined ) {
|
||||
var selected = data[ lang ];
|
||||
for ( key in selected ) {
|
||||
$( ".l10n-" + key ).text( selected[key] );
|
||||
};
|
||||
if ( langs[ lang ] === undefined ) {
|
||||
lang = "en";
|
||||
};
|
||||
|
||||
var storedLang = localStorage.getItem( this.config.store.lang );
|
||||
if ( langs[ storedLang ] !== undefined ) {
|
||||
lang = storedLang;
|
||||
};
|
||||
|
||||
var selected = langs[ lang ];
|
||||
for ( key in selected ) {
|
||||
$( ".l10n-" + key ).text( selected[key] );
|
||||
};
|
||||
$( ".lang" ).text( lang );
|
||||
$( ".langOption" ).removeClass( "current" );
|
||||
$( ".langOption." + lang ).addClass( "current" );
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*******************************
|
||||
* initiate tree indicators
|
||||
*******************************/
|
||||
|
||||
this.initIndicators = function () {
|
||||
|
||||
var THIS = this;
|
||||
$( "#tree .entry.folder:not(.initiatedIndicator)" ).each( function () {
|
||||
|
||||
var $entry = $( this ).addClass( "initiatedIndicator" );
|
||||
var $indicator = $entry.find( "> .indicator" );
|
||||
$indicator.click( function( event ) {
|
||||
if ( $indicator.hasClass( "unknown" ) ) {
|
||||
$.get( "/h5ai/php/treecontent.php", { "href": $entry.find( "> a" ).attr( "href" ) }, function ( html ) {
|
||||
$content = $( html );
|
||||
$indicator.removeClass( "unknown" );
|
||||
if ( $content.find( "> li" ).size() === 0 ) {
|
||||
$indicator.replaceWith( $( "<span class='blank' />" ) );
|
||||
} else {
|
||||
$indicator.addClass( "open" );
|
||||
$entry.find( "> .content" ).replaceWith( $content );
|
||||
$( "#tree" ).get( 0 ).updateScrollbar();
|
||||
THIS.initIndicators();
|
||||
};
|
||||
} );
|
||||
} else if ( $indicator.hasClass( "open" ) ) {
|
||||
$indicator.removeClass( "open" );
|
||||
$( "#tree" ).get( 0 ).updateScrollbar( true );
|
||||
$entry.find( "> .content" ).slideUp( function() {
|
||||
$( "#tree" ).get( 0 ).updateScrollbar();
|
||||
} );
|
||||
} else {
|
||||
$indicator.addClass( "open" );
|
||||
$( "#tree" ).get( 0 ).updateScrollbar( true );
|
||||
$entry.find( "> .content" ).slideDown( function() {
|
||||
$( "#tree" ).get( 0 ).updateScrollbar();
|
||||
} );
|
||||
};
|
||||
} );
|
||||
} );
|
||||
};
|
||||
};
|
||||
|
|
133
src/h5ai/js/inc/jquery.scrollpanel.js
Normal file
|
@ -0,0 +1,133 @@
|
|||
( function ( $ ) {
|
||||
|
||||
var init = function ( htmlElement ) {
|
||||
|
||||
var $element = $( htmlElement );
|
||||
|
||||
if ( $element.css( "position" ) === undefined || $element.css( "position" ) === "static" ) {
|
||||
$element.css( "position", "relative" );
|
||||
};
|
||||
|
||||
var $scrollbar = $( "<div class='scrollbar' />" );
|
||||
var $drag = $( "<div class='drag' />" ).appendTo( $scrollbar );
|
||||
$element
|
||||
.wrapInner( "<div class='wrapper'><div class='content' /></div>" )
|
||||
.append( $scrollbar );
|
||||
var $wrapper = $element.find( "> .wrapper" );
|
||||
var $content = $wrapper.find( "> .content" );
|
||||
var mouseOffsetY = 0;
|
||||
var updateId = undefined;
|
||||
|
||||
var update = function ( repeat ) {
|
||||
if ( updateId !== undefined && !repeat ) {
|
||||
clearInterval( updateId );
|
||||
updateId = undefined;
|
||||
} else if ( updateId === undefined && repeat ) {
|
||||
updateId = setInterval( function() { update( true ); }, 50 );
|
||||
};
|
||||
|
||||
$wrapper.css( "height", $element.height() );
|
||||
var visibleHeight = $element.height();
|
||||
var contentHeight = $content.outerHeight();
|
||||
var scrollTop = $wrapper.scrollTop();
|
||||
var scrollTopFrac = scrollTop / contentHeight;
|
||||
var visVertFrac = Math.min( visibleHeight / contentHeight, 1 );
|
||||
|
||||
if ( visVertFrac < 1 ) {
|
||||
$scrollbar
|
||||
.fadeIn( 50 )
|
||||
.css( {
|
||||
height: $element.innerHeight() + $scrollbar.height() - $scrollbar.outerHeight( true )
|
||||
} );
|
||||
$drag
|
||||
.css( {
|
||||
top: $scrollbar.height() * scrollTopFrac,
|
||||
height: $scrollbar.height() * visVertFrac
|
||||
} );
|
||||
} else {
|
||||
$scrollbar.fadeOut( 50 );
|
||||
};
|
||||
};
|
||||
var scroll = function ( event ) {
|
||||
var clickFrac = ( event.pageY - $scrollbar.offset().top - mouseOffsetY ) / $scrollbar.height();
|
||||
$wrapper.scrollTop( $content.outerHeight() * clickFrac );
|
||||
update();
|
||||
};
|
||||
|
||||
$element
|
||||
.mousewheel( function ( event, delta) {
|
||||
$wrapper.scrollTop( $wrapper.scrollTop() - 50 * delta );
|
||||
update();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
} )
|
||||
.scroll( update );
|
||||
$element.get( 0 ).updateScrollbar = update;
|
||||
$wrapper
|
||||
.css( {
|
||||
"padding-right": $scrollbar.outerWidth( true ),
|
||||
height: $element.height(),
|
||||
overflow: "hidden"
|
||||
} );
|
||||
$scrollbar
|
||||
.css( {
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
right: 0,
|
||||
overflow: "hidden"
|
||||
} )
|
||||
.mousedown( function ( event ) {
|
||||
mouseOffsetY = $drag.outerHeight() / 2;
|
||||
scroll( event );
|
||||
$scrollbar.addClass( "dragOn" );
|
||||
$( window )
|
||||
.bind( "mousemove", scroll )
|
||||
.one( "mouseup", function ( event ) {
|
||||
$scrollbar.removeClass( "dragOn" );
|
||||
$( window ).unbind( "mousemove", scroll );
|
||||
scroll( event );
|
||||
event.stopPropagation();
|
||||
} );
|
||||
event.stopPropagation();
|
||||
} )
|
||||
.attr( "unselectable", "on" )
|
||||
.css( "-moz-user-select", "none" )
|
||||
.each( function () {
|
||||
this.onselectstart = function () {
|
||||
return false;
|
||||
};
|
||||
} );
|
||||
$drag
|
||||
.css( {
|
||||
position: "absolute",
|
||||
left: 0,
|
||||
width: "100%"
|
||||
} )
|
||||
.mousedown( function ( event ) {
|
||||
mouseOffsetY = event.pageY - $drag.offset().top;
|
||||
scroll( event );
|
||||
$scrollbar.addClass( "dragOn" );
|
||||
$( window )
|
||||
.bind( "mousemove", scroll )
|
||||
.one( "mouseup", function ( event ) {
|
||||
$scrollbar.removeClass( "dragOn" );
|
||||
$( window ).unbind( "mousemove", scroll );
|
||||
scroll( event );
|
||||
event.stopPropagation();
|
||||
} );
|
||||
event.stopPropagation();
|
||||
} );
|
||||
|
||||
update();
|
||||
};
|
||||
|
||||
|
||||
$.fn.scrollpanel = function () {
|
||||
|
||||
return this.each( function () {
|
||||
|
||||
init( this );
|
||||
} );
|
||||
};
|
||||
|
||||
} )( jQuery );
|
24
src/h5ai/js/inc/jquery.utils.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
( function( $ ) {
|
||||
|
||||
// http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
|
||||
// modified
|
||||
$.log = function () {
|
||||
$.log.history = $.log.history || [];
|
||||
$.log.history.push( arguments );
|
||||
if ( window.console ) {
|
||||
window.console.log( Array.prototype.slice.call( arguments ) );
|
||||
};
|
||||
};
|
||||
|
||||
var Timer = function () {
|
||||
this.start = new Date().getTime();;
|
||||
this.last = this.start;
|
||||
this.log = function ( label ) {
|
||||
var now = new Date().getTime();
|
||||
$.log( "timer", label, "+" + (now - this.last), "=" + (now - this.start) );
|
||||
this.last = now;
|
||||
};
|
||||
};
|
||||
$.timer = new Timer();
|
||||
|
||||
} )( jQuery );
|
|
@ -170,6 +170,14 @@ var PathCache = function () {
|
|||
|
||||
var Path = function ( pathCache, folder, tableRow ) {
|
||||
|
||||
this.checkedDecodeUri = function ( uri ) {
|
||||
try {
|
||||
return decodeURI( uri );
|
||||
} catch ( err ) {
|
||||
};
|
||||
return uri;
|
||||
}
|
||||
|
||||
if ( ! pathEndsWithSlashRegEx.test( folder ) ) {
|
||||
folder += "/";
|
||||
};
|
||||
|
@ -191,13 +199,13 @@ var Path = function ( pathCache, folder, tableRow ) {
|
|||
|
||||
this.parentFolder = splits[0];
|
||||
this.href = splits[1];
|
||||
this.label = decodeURI( splits[1] );
|
||||
this.label = this.checkedDecodeUri( splits[1] );
|
||||
this.icon16 = "/h5ai/icons/16x16/folder.png";
|
||||
this.alt = "[DIR]";
|
||||
this.date = "";
|
||||
this.size = "";
|
||||
if ( this.label === "/" ) {
|
||||
this.label = decodeURI( document.domain ) + "/";
|
||||
this.label = this.checkedDecodeUri( document.domain ) + "/";
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -214,9 +222,9 @@ var Path = function ( pathCache, folder, tableRow ) {
|
|||
|
||||
if ( this.isParentFolder && h5ai.config.setParentFolderLabels ) {
|
||||
if ( this.isDomain ) {
|
||||
this.label = decodeURI( document.domain );
|
||||
this.label = this.checkedDecodeUri( document.domain );
|
||||
} else {
|
||||
this.label = decodeURI( pathCache.splitPathname( pathCache.splitPathname( this.parentFolder )[0] )[1].slice( 0, -1 ) );
|
||||
this.label = this.checkedDecodeUri( pathCache.splitPathname( pathCache.splitPathname( this.parentFolder )[0] )[1].slice( 0, -1 ) );
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -237,37 +245,10 @@ var Path = function ( pathCache, folder, tableRow ) {
|
|||
|
||||
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();
|
||||
|
@ -292,7 +273,6 @@ var Path = function ( pathCache, folder, tableRow ) {
|
|||
var $a = $( "<a><img src='/h5ai/images/crumb.png' alt='>' />" + this.label + "</a>" );
|
||||
$a.attr( "href", this.absHref );
|
||||
$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 ) {
|
||||
|
@ -340,7 +320,6 @@ var Path = function ( pathCache, folder, tableRow ) {
|
|||
var $a = $( "<a />" ).appendTo( $html );
|
||||
$a.attr( "href", this.absHref );
|
||||
$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 );
|
||||
|
@ -391,7 +370,6 @@ var Path = function ( pathCache, folder, tableRow ) {
|
|||
.append( $( "<span class='label'>" + this.label + "</span>" ) );
|
||||
$a.attr( "href", this.absHref );
|
||||
$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
|
||||
|
@ -409,6 +387,7 @@ var Path = function ( pathCache, folder, tableRow ) {
|
|||
this.content = content;
|
||||
this.treeOpen = true;
|
||||
pathCache.objectCache[this.absHref] = pathCache.pathToObject( this );
|
||||
pathCache.storeCache();
|
||||
$( "#tree" ).get( 0 ).updateScrollbar( true );
|
||||
this.updateTreeHtml( function() {
|
||||
$( "#tree" ).get( 0 ).updateScrollbar();
|
||||
|
@ -417,6 +396,7 @@ var Path = function ( pathCache, folder, tableRow ) {
|
|||
} else if ( $indicator.hasClass( "open" ) ) {
|
||||
this.treeOpen = false;
|
||||
pathCache.objectCache[this.absHref] = pathCache.pathToObject( this );
|
||||
pathCache.storeCache();
|
||||
$indicator.removeClass( "open" );
|
||||
$( "#tree" ).get( 0 ).updateScrollbar( true );
|
||||
$html.find( "> ul.content" ).slideUp( function() {
|
||||
|
@ -425,6 +405,7 @@ var Path = function ( pathCache, folder, tableRow ) {
|
|||
} else {
|
||||
this.treeOpen = true;
|
||||
pathCache.objectCache[this.absHref] = pathCache.pathToObject( this );
|
||||
pathCache.storeCache();
|
||||
$indicator.addClass( "open" );
|
||||
$( "#tree" ).get( 0 ).updateScrollbar( true );
|
||||
$html.find( "> ul.content" ).slideDown( function() {
|
||||
|
@ -432,6 +413,7 @@ var Path = function ( pathCache, folder, tableRow ) {
|
|||
} );
|
||||
};
|
||||
}, this ) );
|
||||
$html.addClass( "initiatedIndicator" );
|
||||
$blank.replaceWith( $indicator );
|
||||
};
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
|
||||
var Tree = function ( pathCache, h5ai ) {
|
||||
|
||||
var THIS = this;
|
||||
var contentTypeRegEx = /^text\/html;h5ai=/;
|
||||
|
||||
this.init = function () {
|
||||
|
||||
|
@ -21,6 +19,7 @@ var Tree = function ( pathCache, h5ai ) {
|
|||
path.status = status;
|
||||
};
|
||||
path.updateHtml();
|
||||
h5ai.linkHoverStates();
|
||||
} );
|
||||
};
|
||||
};
|
||||
|
@ -36,34 +35,16 @@ var Tree = function ( pathCache, h5ai ) {
|
|||
|
||||
this.populateTree = function () {
|
||||
|
||||
var $tree = $( "#tree" );
|
||||
var $extended = $( "#extended" );
|
||||
var shiftTree = function ( forceVisible, dontAnimate ) {
|
||||
if ( $tree.outerWidth() < $extended.offset().left || forceVisible === true ) {
|
||||
if ( dontAnimate === true ) {
|
||||
$tree.stop().css( { left: 0 } );
|
||||
} else {
|
||||
$tree.stop().animate( { left: 0 } );
|
||||
};
|
||||
} else {
|
||||
if ( dontAnimate === true ) {
|
||||
$tree.stop().css( { left: 18 - $tree.outerWidth() } );
|
||||
} else {
|
||||
$tree.stop().animate( { left: 18 - $tree.outerWidth() } );
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
$tree.hover( function () { shiftTree( true ); }, function () { shiftTree(); } );
|
||||
$( window ).resize( function() {
|
||||
shiftTree();
|
||||
} );
|
||||
|
||||
this.fetchTree( document.location.pathname, function( path ) {
|
||||
$tree.append( path.updateTreeHtml() );
|
||||
$tree.show();
|
||||
scrollpanel( $tree );
|
||||
shiftTree( false, true );
|
||||
$( "#tree" )
|
||||
.append( path.updateTreeHtml() )
|
||||
.scrollpanel()
|
||||
.show();
|
||||
h5ai.linkHoverStates();
|
||||
pathCache.storeCache();
|
||||
setTimeout( function () {
|
||||
$( "#tree" ).get( 0 ).updateScrollbar();
|
||||
}, 1 );
|
||||
} );
|
||||
};
|
||||
|
||||
|
@ -99,6 +80,11 @@ var Tree = function ( pathCache, h5ai ) {
|
|||
};
|
||||
|
||||
|
||||
|
||||
var THIS = this;
|
||||
var contentTypeRegEx = /^text\/html;h5ai=/;
|
||||
var pathnameStatusCache = {};
|
||||
|
||||
this.fetchStatusAndContent = function ( pathname, includeParent, callback ) {
|
||||
|
||||
this.fetchStatus( pathname, function ( status ) {
|
||||
|
@ -136,8 +122,6 @@ var Tree = function ( pathCache, h5ai ) {
|
|||
};
|
||||
|
||||
|
||||
var pathnameStatusCache = {};
|
||||
|
||||
this.fetchStatus = function ( pathname, callback ) {
|
||||
|
||||
if ( h5ai.config.folderStatus[ pathname ] !== undefined ) {
|
||||
|
@ -161,127 +145,4 @@ var Tree = function ( pathCache, h5ai ) {
|
|||
}
|
||||
} );
|
||||
};
|
||||
|
||||
|
||||
var scrollpanel = function ( htmlElement ) {
|
||||
|
||||
var $element = $( htmlElement );
|
||||
|
||||
if ( $element.css( "position" ) === undefined || $element.css( "position" ) === "static" ) {
|
||||
$element.css( "position", "relative" );
|
||||
};
|
||||
|
||||
var $scrollbar = $( "<div class='scrollbar' />" );
|
||||
var $drag = $( "<div class='drag' />" ).appendTo( $scrollbar );
|
||||
$element
|
||||
.wrapInner( "<div class='wrapper'><div class='content' /></div>" )
|
||||
.append( $scrollbar );
|
||||
var $wrapper = $element.find( "> .wrapper" );
|
||||
var $content = $wrapper.find( "> .content" );
|
||||
var mouseOffsetY = 0;
|
||||
var updateId = undefined;
|
||||
|
||||
var update = function ( repeat ) {
|
||||
if ( updateId !== undefined && !repeat ) {
|
||||
clearInterval( updateId );
|
||||
updateId = undefined;
|
||||
} else if ( updateId === undefined && repeat ) {
|
||||
updateId = setInterval( function() { update( true ); }, 50 );
|
||||
};
|
||||
|
||||
$wrapper.css( "height", $element.height() );
|
||||
var visibleHeight = $element.height();
|
||||
var contentHeight = $content.outerHeight();
|
||||
var scrollTop = $wrapper.scrollTop();
|
||||
var scrollTopFrac = scrollTop / contentHeight;
|
||||
var visVertFrac = Math.min( visibleHeight / contentHeight, 1 );
|
||||
|
||||
if ( visVertFrac < 1 ) {
|
||||
$scrollbar
|
||||
.fadeIn( 50 )
|
||||
.css( {
|
||||
height: $element.innerHeight() + $scrollbar.height() - $scrollbar.outerHeight( true )
|
||||
} );
|
||||
$drag
|
||||
.css( {
|
||||
top: $scrollbar.height() * scrollTopFrac,
|
||||
height: $scrollbar.height() * visVertFrac
|
||||
} );
|
||||
} else {
|
||||
$scrollbar.fadeOut( 50 );
|
||||
};
|
||||
};
|
||||
var scroll = function ( event ) {
|
||||
var clickFrac = ( event.pageY - $scrollbar.offset().top - mouseOffsetY ) / $scrollbar.height();
|
||||
$wrapper.scrollTop( $content.outerHeight() * clickFrac );
|
||||
update();
|
||||
};
|
||||
|
||||
$element
|
||||
.mousewheel( function ( event, delta) {
|
||||
$wrapper.scrollTop( $wrapper.scrollTop() - 50 * delta );
|
||||
update();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
} )
|
||||
.scroll( update );
|
||||
$element.get( 0 ).updateScrollbar = update;
|
||||
$wrapper
|
||||
.css( {
|
||||
"padding-right": $scrollbar.outerWidth( true ),
|
||||
height: $element.height(),
|
||||
overflow: "hidden"
|
||||
} );
|
||||
$scrollbar
|
||||
.css( {
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
right: 0,
|
||||
overflow: "hidden"
|
||||
} )
|
||||
.mousedown( function ( event ) {
|
||||
mouseOffsetY = $drag.outerHeight() / 2;
|
||||
scroll( event );
|
||||
$scrollbar.addClass( "dragOn" );
|
||||
$( window )
|
||||
.bind( "mousemove", scroll )
|
||||
.one( "mouseup", function ( event ) {
|
||||
$scrollbar.removeClass( "dragOn" );
|
||||
$( window ).unbind( "mousemove", scroll );
|
||||
scroll( event );
|
||||
event.stopPropagation();
|
||||
} );
|
||||
event.stopPropagation();
|
||||
} )
|
||||
.attr( "unselectable", "on" )
|
||||
.css( "-moz-user-select", "none" )
|
||||
.each( function () {
|
||||
this.onselectstart = function () {
|
||||
return false;
|
||||
};
|
||||
} );
|
||||
$drag
|
||||
.css( {
|
||||
position: "absolute",
|
||||
left: 0,
|
||||
width: "100%"
|
||||
} )
|
||||
.mousedown( function ( event ) {
|
||||
mouseOffsetY = event.pageY - $drag.offset().top;
|
||||
scroll( event );
|
||||
$scrollbar.addClass( "dragOn" );
|
||||
$( window )
|
||||
.bind( "mousemove", scroll )
|
||||
.one( "mouseup", function ( event ) {
|
||||
$scrollbar.removeClass( "dragOn" );
|
||||
$( window ).unbind( "mousemove", scroll );
|
||||
scroll( event );
|
||||
event.stopPropagation();
|
||||
} );
|
||||
event.stopPropagation();
|
||||
} );
|
||||
|
||||
update();
|
||||
};
|
||||
|
||||
};
|
||||
|
|
44
src/h5ai/js/main-js.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
( function( $ ) {
|
||||
|
||||
// @include "inc/jquery.json.min.js"
|
||||
// @include "inc/jquery.mousewheel.min.js"
|
||||
// @include "inc/jquery.scrollpanel.js"
|
||||
// @include "inc/jquery.utils.js"
|
||||
// @include "inc/path.js"
|
||||
// @include "inc/extended.js"
|
||||
// @include "inc/h5ai.js"
|
||||
// @include "inc/tree.js"
|
||||
|
||||
|
||||
/*******************************
|
||||
* create
|
||||
*******************************/
|
||||
|
||||
$.timer.log( "start pathcache" );
|
||||
var pathCache = new PathCache();
|
||||
$.timer.log( "end pathcache" );
|
||||
var extended = new Extended( pathCache );
|
||||
var h5ai = new H5ai( h5aiOptions, h5aiLangs );
|
||||
var tree = new Tree( pathCache, h5ai );
|
||||
|
||||
|
||||
/*******************************
|
||||
* register public api
|
||||
*******************************/
|
||||
|
||||
$.h5ai = {
|
||||
click: $.proxy( h5ai.pathClick, h5ai )
|
||||
};
|
||||
|
||||
/*******************************
|
||||
* init after dom load
|
||||
*******************************/
|
||||
|
||||
$( function() {
|
||||
|
||||
extended.init();
|
||||
tree.init();
|
||||
h5ai.init();
|
||||
} );
|
||||
|
||||
} )( jQuery );
|
36
src/h5ai/js/main-php.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
( function( $ ) {
|
||||
|
||||
// @include "inc/jquery.json.min.js"
|
||||
// @include "inc/jquery.mousewheel.min.js"
|
||||
// @include "inc/jquery.scrollpanel.js"
|
||||
// @include "inc/jquery.utils.js"
|
||||
// @include "inc/h5ai.js"
|
||||
|
||||
|
||||
/*******************************
|
||||
* create
|
||||
*******************************/
|
||||
|
||||
var h5ai = new H5ai( h5aiOptions, h5aiLangs );
|
||||
|
||||
|
||||
/*******************************
|
||||
* register public api
|
||||
*******************************/
|
||||
|
||||
$.h5ai = {
|
||||
click: $.proxy( h5ai.pathClick, h5ai )
|
||||
};
|
||||
|
||||
|
||||
/*******************************
|
||||
* init after dom load
|
||||
*******************************/
|
||||
|
||||
$( function() {
|
||||
|
||||
h5ai.init();
|
||||
$( "#tree" ).scrollpanel();
|
||||
} );
|
||||
|
||||
} )( jQuery );
|
|
@ -1,66 +0,0 @@
|
|||
( function( $ ) {
|
||||
|
||||
// @include "inc/jquery.json.min.js"
|
||||
// @include "inc/jquery.mousewheel.min.js"
|
||||
// @include "inc/path.js"
|
||||
// @include "inc/h5ai.js"
|
||||
// @include "inc/tree.js"
|
||||
|
||||
// http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
|
||||
$.log = function () {
|
||||
$.log.history = $.log.history || [];
|
||||
$.log.history.push( arguments );
|
||||
if ( window.console ) {
|
||||
window.console.log( Array.prototype.slice.call( arguments ) );
|
||||
};
|
||||
};
|
||||
|
||||
var Timer = function () {
|
||||
this.start = new Date().getTime();;
|
||||
this.last = this.start;
|
||||
this.log = function ( label ) {
|
||||
var now = new Date().getTime();
|
||||
$.log( "timer", label, "+" + (now - this.last), "=" + (now - this.start) );
|
||||
this.last = now;
|
||||
};
|
||||
};
|
||||
$.timer = new Timer();
|
||||
|
||||
|
||||
/*******************************
|
||||
* create
|
||||
*******************************/
|
||||
|
||||
$.timer.log( "start pathcache" );
|
||||
var pathCache = new PathCache();
|
||||
$.timer.log( "end pathcache" );
|
||||
var h5ai = new H5ai( h5aiOptions, h5aiLangs, pathCache );
|
||||
var tree = new Tree( pathCache, h5ai );
|
||||
|
||||
|
||||
/*******************************
|
||||
* register public api
|
||||
*******************************/
|
||||
|
||||
$.h5ai = {
|
||||
click: $.proxy( h5ai.pathClick, h5ai )
|
||||
};
|
||||
|
||||
/*******************************
|
||||
* init after dom load
|
||||
*******************************/
|
||||
|
||||
$( function() {
|
||||
h5ai.init();
|
||||
tree.init();
|
||||
|
||||
// just for testing, resets the local cache /////////
|
||||
$( ".l10n-footerUsing" ).click( function () {
|
||||
pathCache.cache = {};
|
||||
pathCache.objectCache = {};
|
||||
pathCache.storeCache();
|
||||
} );
|
||||
/////////////////////////////////////////////////////
|
||||
} );
|
||||
|
||||
} )( jQuery );
|
|
@ -13,7 +13,7 @@ h5aiOptions = {
|
|||
* The user selected view mode is also stored local in modern browsers
|
||||
* so that it will be persistent.
|
||||
*/
|
||||
viewmodes: [ "details", "icons" ],
|
||||
"viewmodes": [ "details", "icons" ],
|
||||
|
||||
/*
|
||||
* Show a folder tree, boolean.
|
||||
|
@ -22,7 +22,7 @@ h5aiOptions = {
|
|||
* 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
|
||||
|
@ -34,7 +34,7 @@ h5aiOptions = {
|
|||
* as a non auto indexed folder, that means a folder containing an
|
||||
* appropriate default index file.
|
||||
*/
|
||||
folderStatus: {
|
||||
"folderStatus": {
|
||||
/*
|
||||
* for example:
|
||||
* "/some/folder/": 200
|
||||
|
@ -44,132 +44,189 @@ h5aiOptions = {
|
|||
/*
|
||||
* 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.
|
||||
* h5aiLangs it defaults to "en".
|
||||
*/
|
||||
lang: undefined,
|
||||
"lang": null,
|
||||
|
||||
/*
|
||||
* Try to use browser language, falls back to previous specified lang.
|
||||
*/
|
||||
useBrowserLang: true,
|
||||
"useBrowserLang": true,
|
||||
|
||||
/*
|
||||
* Set parent folder labels to real folder names.
|
||||
*/
|
||||
setParentFolderLabels: true,
|
||||
"setParentFolderLabels": true,
|
||||
|
||||
/*
|
||||
* Link the hover effects between crumb, extended view and tree.
|
||||
*/
|
||||
linkHoverStates: true
|
||||
"linkHoverStates": true,
|
||||
|
||||
/*
|
||||
* Only used in PHP implementation.
|
||||
* Date format in PHP syntax, for example: "Y-m-d H:i:s"
|
||||
* http://www.php.net/manual/en/function.date.php
|
||||
*/
|
||||
"dateFormat": "Y-m-d H:i",
|
||||
|
||||
/*
|
||||
* Only used in PHP implementation.
|
||||
* Files/folders that should never be listed. Specified
|
||||
* by the complete filename or by a regular expression.
|
||||
* http://www.php.net/manual/en/function.preg-match.php
|
||||
*/
|
||||
"ignore": [ "h5ai", "h5ai.header.html", "h5ai.footer.html" ],
|
||||
"ignoreRE": [ "/^\\./" ]
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* 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",
|
||||
empty: "empty"
|
||||
"lang": "english",
|
||||
"details": "details",
|
||||
"icons": "icons",
|
||||
"name": "Name",
|
||||
"lastModified": "Last modified",
|
||||
"size": "Size",
|
||||
"parentDirectory": "Parent Directory",
|
||||
"empty": "empty",
|
||||
"folders": "folders",
|
||||
"files": "files"
|
||||
},
|
||||
|
||||
"de": {
|
||||
viewDetails: "Details",
|
||||
viewIcons: "Icons",
|
||||
columnName: "Name",
|
||||
columnLastModified: "Geändert",
|
||||
columnSize: "Größe",
|
||||
footerUsing: "nutzt",
|
||||
parentDirectory: "Übergeordnetes Verzeichnis",
|
||||
empty: "leer"
|
||||
"lang": "deutsch",
|
||||
"details": "Details",
|
||||
"icons": "Icons",
|
||||
"name": "Name",
|
||||
"lastModified": "Geändert",
|
||||
"size": "Größe",
|
||||
"parentDirectory": "Übergeordnetes Verzeichnis",
|
||||
"empty": "leer",
|
||||
"folders": "Ordner",
|
||||
"files": "Dateien"
|
||||
},
|
||||
|
||||
"fr": {
|
||||
viewDetails: "détails",
|
||||
viewIcons: "icônes",
|
||||
columnName: "Nom",
|
||||
columnLastModified: "Dernière modification",
|
||||
columnSize: "Taille",
|
||||
footerUsing: "utilise",
|
||||
parentDirectory: "Dossier parent",
|
||||
empty: "vide"
|
||||
"lang": "française",
|
||||
"details": "détails",
|
||||
"icons": "icônes",
|
||||
"name": "Nom",
|
||||
"lastModified": "Dernière modification",
|
||||
"size": "Taille",
|
||||
"parentDirectory": "Dossier parent",
|
||||
"empty": "vide",
|
||||
"folders": "[?folders?]",
|
||||
"files": "[?files?]"
|
||||
},
|
||||
|
||||
"nl": {
|
||||
viewDetails: "details",
|
||||
viewIcons: "iconen",
|
||||
columnName: "Naam",
|
||||
columnLastModified: "Laatste wijziging",
|
||||
columnSize: "Grootte",
|
||||
footerUsing: "gebruikt",
|
||||
parentDirectory: "Bovenliggende map",
|
||||
empty: "lege"
|
||||
"lang": "nederlands",
|
||||
"details": "details",
|
||||
"icons": "iconen",
|
||||
"name": "Naam",
|
||||
"lastModified": "Laatste wijziging",
|
||||
"size": "Grootte",
|
||||
"parentDirectory": "Bovenliggende map",
|
||||
"empty": "lege",
|
||||
"folders": "[?folders?]",
|
||||
"files": "[?files?]"
|
||||
},
|
||||
|
||||
"sv": {
|
||||
viewDetails: "detaljerad",
|
||||
viewIcons: "ikoner",
|
||||
columnName: "Filnamn",
|
||||
columnLastModified: "Senast ändrad",
|
||||
columnSize: "Filstorlek",
|
||||
footerUsing: "använder",
|
||||
parentDirectory: "Till överordnad mapp",
|
||||
empty: "tom"
|
||||
"lang": "svenska",
|
||||
"details": "detaljerad",
|
||||
"icons": "ikoner",
|
||||
"name": "Filnamn",
|
||||
"lastModified": "Senast ändrad",
|
||||
"size": "Filstorlek",
|
||||
"parentDirectory": "Till överordnad mapp",
|
||||
"empty": "tom",
|
||||
"folders": "[?folders?]",
|
||||
"files": "[?files?]"
|
||||
},
|
||||
|
||||
"cs": {
|
||||
viewDetails: "podrobnosti",
|
||||
viewIcons: "ikony",
|
||||
columnName: "Název",
|
||||
columnLastModified: "Upraveno",
|
||||
columnSize: "Velikost",
|
||||
footerUsing: "používá",
|
||||
parentDirectory: "Nadřazený adresář",
|
||||
empty: "prázdný"
|
||||
"lang": "[?lang?]",
|
||||
"details": "podrobnosti",
|
||||
"icons": "ikony",
|
||||
"name": "Název",
|
||||
"lastModified": "Upraveno",
|
||||
"size": "Velikost",
|
||||
"parentDirectory": "Nadřazený adresář",
|
||||
"empty": "prázdný",
|
||||
"folders": "[?folders?]",
|
||||
"files": "[?files?]"
|
||||
},
|
||||
|
||||
"sk": {
|
||||
viewDetails: "podrobnosti",
|
||||
viewIcons: "ikony",
|
||||
columnName: "Názov",
|
||||
columnLastModified: "Upravené",
|
||||
columnSize: "Velkosť",
|
||||
footerUsing: "používá",
|
||||
parentDirectory: "Nadriadený priečinok",
|
||||
empty: "prázdny"
|
||||
"lang": "[?lang?]",
|
||||
"details": "podrobnosti",
|
||||
"icons": "ikony",
|
||||
"name": "Názov",
|
||||
"lastModified": "Upravené",
|
||||
"size": "Velkosť",
|
||||
"parentDirectory": "Nadriadený priečinok",
|
||||
"empty": "prázdny",
|
||||
"folders": "[?folders?]",
|
||||
"files": "[?files?]"
|
||||
},
|
||||
|
||||
"es": {
|
||||
viewDetails: "Detalles",
|
||||
viewIcons: "Íconos",
|
||||
columnName: "Nombre",
|
||||
columnLastModified: "Última modificación",
|
||||
columnSize: "Tamaño",
|
||||
footerUsing: "usando",
|
||||
parentDirectory: "Directorio superior",
|
||||
empty: "vacío"
|
||||
"lang": "español",
|
||||
"details": "Detalles",
|
||||
"icons": "Íconos",
|
||||
"name": "Nombre",
|
||||
"lastModified": "Última modificación",
|
||||
"size": "Tamaño",
|
||||
"parentDirectory": "Directorio superior",
|
||||
"empty": "vacío",
|
||||
"folders": "[?folders?]",
|
||||
"files": "[?files?]"
|
||||
},
|
||||
|
||||
"tr": {
|
||||
viewDetails: "detaylar",
|
||||
viewIcons: "ikonlar",
|
||||
columnName: "İsim",
|
||||
columnLastModified: "Son Düzenleme",
|
||||
columnSize: "Boyut",
|
||||
footerUsing: "kullanıyor",
|
||||
parentDirectory: "Üst Dizin",
|
||||
empty: "boş"
|
||||
}
|
||||
"lang": "türkçe",
|
||||
"details": "detaylar",
|
||||
"icons": "ikonlar",
|
||||
"name": "İsim",
|
||||
"lastModified": "Son Düzenleme",
|
||||
"size": "Boyut",
|
||||
"parentDirectory": "Üst Dizin",
|
||||
"empty": "boş",
|
||||
"folders": "[?folders?]",
|
||||
"files": "[?files?]"
|
||||
},
|
||||
|
||||
"pt": {
|
||||
"lang": "português",
|
||||
"details": "detalhes",
|
||||
"icons": "ícones",
|
||||
"name": "Nome",
|
||||
"lastModified": "Última modificação",
|
||||
"size": "Tamanho",
|
||||
"parentDirectory": "Diretório superior",
|
||||
"empty": "vazio",
|
||||
"folders": "[?folders?]",
|
||||
"files": "[?files?]"
|
||||
},
|
||||
|
||||
"bg": {
|
||||
"lang": "[?lang?]",
|
||||
"details": "детайли",
|
||||
"icons": "икони",
|
||||
"name": "Име",
|
||||
"lastModified": "Последна промяна",
|
||||
"size": "Размер",
|
||||
"parentDirectory": "Предходна директория",
|
||||
"empty": "празно",
|
||||
"folders": "[?folders?]",
|
||||
"files": "[?files?]"
|
||||
}
|
||||
};
|
||||
|
|
93
src/h5ai/php/cache.php
Normal file
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
##############################################
|
||||
# taken from here:
|
||||
# http://www.jongales.com/blog/2009/02/18/simple-file-based-php-cache-class/
|
||||
# with minor modifications
|
||||
##############################################
|
||||
|
||||
class Cache {
|
||||
private $dir;
|
||||
|
||||
function __construct( $dir ) {
|
||||
|
||||
$this->dir = $dir;
|
||||
}
|
||||
|
||||
private function _name( $key ) {
|
||||
|
||||
return $this->dir . "/" . sha1( $key );
|
||||
}
|
||||
|
||||
public function get( $key, $expiration = 3600 ) {
|
||||
|
||||
if ( !is_dir( $this->dir ) || !is_writable( $this->dir ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cache_path = $this->_name( $key );
|
||||
|
||||
if ( !@file_exists( $cache_path ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( filemtime( $cache_path ) < ( time() - $expiration ) ) {
|
||||
$this->clear( $key );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !$fp = @fopen( $cache_path, "rb" ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
flock( $fp, LOCK_SH );
|
||||
$cache = "";
|
||||
|
||||
if ( filesize( $cache_path ) > 0 ) {
|
||||
$cache = unserialize( fread( $fp, filesize( $cache_path ) ) );
|
||||
} else {
|
||||
$cache = null;
|
||||
}
|
||||
|
||||
flock( $fp, LOCK_UN );
|
||||
fclose( $fp );
|
||||
|
||||
return $cache;
|
||||
}
|
||||
|
||||
public function set( $key, $data ) {
|
||||
|
||||
if ( !is_dir( $this->dir ) || !is_writable( $this->dir ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cache_path = $this->_name( $key );
|
||||
|
||||
if ( ! $fp = fopen( $cache_path, "wb" ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( flock( $fp, LOCK_EX ) ) {
|
||||
fwrite( $fp, serialize( $data ) );
|
||||
flock( $fp, LOCK_UN );
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
fclose( $fp );
|
||||
@chmod( $cache_path, 0777 );
|
||||
return true;
|
||||
}
|
||||
|
||||
public function clear( $key ) {
|
||||
|
||||
$cache_path = $this->_name( $key );
|
||||
|
||||
if ( file_exists( $cache_path ) ) {
|
||||
unlink( $cache_path );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
52
src/h5ai/php/crumb.php
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
class Crumb {
|
||||
private $h5ai, $parts;
|
||||
|
||||
public function __construct( $h5ai ) {
|
||||
|
||||
$this->h5ai = $h5ai;
|
||||
$this->parts = array();
|
||||
|
||||
$href = $h5ai->getAbsHref();
|
||||
while ( $href !== "/" && $href !== "//" ) {
|
||||
$this->parts[] = $href;
|
||||
$href = dirname( $href ) . "/";
|
||||
}
|
||||
$this->parts[] = "/";
|
||||
|
||||
$this->parts = array_reverse( $this->parts );
|
||||
}
|
||||
|
||||
public function toHtml() {
|
||||
|
||||
$html = "";
|
||||
$idx = 0;
|
||||
foreach( $this->parts as $href ) {
|
||||
$idx++;
|
||||
$classes = "crumb folder" . ( $idx === 1 ? " domain" : "" ) . ( $idx === count( $this->parts ) ? " current" : "" );
|
||||
$image = "/h5ai/images/" . ( $idx === 1 ? "home.png" : "crumb.png" );
|
||||
$label = $this->h5ai->getLabel( $href );
|
||||
$hint = "";
|
||||
|
||||
$code = $this->h5ai->getHttpCode( $href );
|
||||
$classes .= " checkedHttpCode";
|
||||
if ( $code !== "h5ai" ) {
|
||||
if ( $code === 200 ) {
|
||||
$hint = "<img class='hint' src='/h5ai/images/page.png' alt='page' />";
|
||||
} else {
|
||||
$hint = "<span class='hint'>(" . $code . ")</span>";
|
||||
}
|
||||
}
|
||||
|
||||
$html .= "<li class='$classes'>\n";
|
||||
$html .= "\t<a href='$href'>\n";
|
||||
$html .= "\t\t<img src='$image' alt='>' />" . $label . $hint . "\n";
|
||||
$html .= "\t</a>\n";
|
||||
$html .= "</li>\n";
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
27
src/h5ai/php/customize.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
class Customize {
|
||||
private $h5ai;
|
||||
|
||||
public function __construct( $h5ai ) {
|
||||
|
||||
$this->h5ai = $h5ai;
|
||||
}
|
||||
|
||||
public function getHeader() {
|
||||
|
||||
return $this->getContent( $this->h5ai->getAbsPath() . "/" . "h5ai.header.html", "header" );
|
||||
}
|
||||
|
||||
public function getFooter() {
|
||||
|
||||
return $this->getContent( $this->h5ai->getAbsPath() . "/" . "h5ai.footer.html", "footer" );
|
||||
}
|
||||
|
||||
private function getContent( $file, $tag ) {
|
||||
|
||||
return file_exists( $file ) ? ( "<" . $tag . ">" . file_get_contents( $file ) . "</" . $tag . ">" ) : "";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
205
src/h5ai/php/extended.php
Normal file
|
@ -0,0 +1,205 @@
|
|||
<?php
|
||||
|
||||
class Entry {
|
||||
private $h5ai, $label, $absPath, $absHref, $date, $isFolder, $type, $size;
|
||||
|
||||
public function __construct( $h5ai, $absPath, $absHref, $type = null, $label = null ) {
|
||||
|
||||
$this->h5ai = $h5ai;
|
||||
$this->label = $label !== null ? $label : $this->h5ai->getLabel( $absHref );
|
||||
$this->absPath = $this->h5ai->normalizePath( $absPath, false );
|
||||
$this->isFolder = is_dir( $this->absPath );
|
||||
$this->absHref = $this->h5ai->normalizePath( $absHref, $this->isFolder );
|
||||
|
||||
$this->date = filemtime( $this->absPath );
|
||||
|
||||
if ( $this->isFolder ) {
|
||||
$this->type = $type !== null ? $type : "folder";
|
||||
$this->size = "";
|
||||
} else {
|
||||
$this->type = $type !== null ? $type : $this->h5ai->getType( $this->absPath );
|
||||
$this->size = filesize( $this->absPath );
|
||||
}
|
||||
}
|
||||
|
||||
public function isFolder() {
|
||||
|
||||
return $this->isFolder;
|
||||
}
|
||||
|
||||
function compare( $that, $sortOrder ) {
|
||||
|
||||
if ( $this->isFolder && !$that->isFolder ) {
|
||||
return -1;
|
||||
}
|
||||
if ( !$this->isFolder && $that->isFolder ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$res = 0;
|
||||
if ( $sortOrder[ "column" ] === "name" ) {
|
||||
$res = strcasecmp( $this->absPath, $that->absPath );
|
||||
} else if ( $sortOrder[ "column" ] === "date" ) {
|
||||
$res = $this->date - $that->date;
|
||||
} else if ( $sortOrder[ "column" ] === "size" ) {
|
||||
$res = $this->size - $that->size;
|
||||
}
|
||||
if ( ! $sortOrder[ "ascending" ] ) {
|
||||
$res = -$res;
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function toHtml( $dateFormat ) {
|
||||
|
||||
$classes = "entry " . $this->type;
|
||||
$img = $this->type;
|
||||
$hint = "";
|
||||
$dateLabel = date( $dateFormat, $this->date );
|
||||
|
||||
if ( $this->isFolder && $this->type !== "folder-parent" ) {
|
||||
$code = $this->h5ai->getHttpCode( $this->absHref );
|
||||
$classes .= " checkedHttpCode";
|
||||
if ( $code !== "h5ai" ) {
|
||||
if ( $code === 200 ) {
|
||||
$img = "folder-page";
|
||||
} else {
|
||||
$classes .= " error";
|
||||
$hint = "<span class='hint'> " . $code . " </span>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$html = "\t<li class='" . $classes . "'>\n";
|
||||
$html .= "\t\t<a href='" . $this->absHref . "'>\n";
|
||||
$html .= "\t\t\t<span class='icon small'><img src='/h5ai/icons/16x16/" . $img . ".png' alt='" . $img . "' /></span>\n";
|
||||
$html .= "\t\t\t<span class='icon big'><img src='/h5ai/icons/48x48/" . $img . ".png' alt='" . $img . "' /></span>\n";
|
||||
$html .= "\t\t\t<span class='label'>" . $this->label . $hint . "</span>\n";
|
||||
$html .= "\t\t\t<span class='date'>" . $dateLabel . "</span>\n";
|
||||
$html .= "\t\t\t<span class='size'>" . $this->formatSize( $this->size ) . "</span>\n";
|
||||
$html .= "\t\t</a>\n";
|
||||
$html .= "\t</li>\n";
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
private function formatSize( $size ) {
|
||||
|
||||
$units = array( 'B', 'KB', 'MB', 'GB', 'TB' );
|
||||
for ( $i = 0; $size >= 1024 && $i < 4; $i++ ) {
|
||||
$size /= 1024;
|
||||
}
|
||||
return round( $size, 0 ) . " " . $units[$i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Extended {
|
||||
private $h5ai, $parent, $content;
|
||||
|
||||
public function __construct( $h5ai ) {
|
||||
|
||||
$this->h5ai = $h5ai;
|
||||
$this->parent = null;
|
||||
$this->content = array();
|
||||
$this->loadContent();
|
||||
}
|
||||
|
||||
private function loadContent() {
|
||||
|
||||
if ( $this->h5ai->getAbsHref() !== "/" ) {
|
||||
$options = $this->h5ai->getOptions();
|
||||
$parentPath = dirname( $this->h5ai->getAbsPath() );
|
||||
$parentHref = dirname( $this->h5ai->getAbsHref() );
|
||||
$label = $options["setParentFolderLabels"] === true ? $this->h5ai->getLabel( $parentHref ) : "<span class='l10n-parentDirectory'>Parent Directory</span>";
|
||||
$this->parent = new Entry( $this->h5ai, $parentPath, $parentHref, "folder-parent", $label );
|
||||
}
|
||||
|
||||
$this->content = array();
|
||||
|
||||
$files = $this->h5ai->readDir( $this->h5ai->getAbsPath() );
|
||||
foreach ( $files as $file ) {
|
||||
$absPath = $this->h5ai->getAbsPath() . "/" . $file;
|
||||
$absHref = $this->h5ai->getAbsHref() . rawurlencode( $file );
|
||||
$this->content[$absPath] = new Entry( $this->h5ai, $absPath, $absHref );
|
||||
}
|
||||
|
||||
$this->sort();
|
||||
}
|
||||
|
||||
public function cmpEntries( $p1, $p2 ) {
|
||||
|
||||
return $p1->compare( $p2, $this->h5ai->getSortOrder() );
|
||||
}
|
||||
|
||||
public function sort() {
|
||||
|
||||
uasort( $this->content, array( $this, "cmpEntries" ) );
|
||||
}
|
||||
|
||||
public function getFolderCount() {
|
||||
|
||||
$count = 0;
|
||||
foreach( $this->content as $entry ) {
|
||||
if ( $entry->isFolder() ) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
public function getFileCount() {
|
||||
|
||||
$count = 0;
|
||||
foreach( $this->content as $entry ) {
|
||||
if ( !$entry->isFolder() ) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
public function toHtml() {
|
||||
|
||||
$html = "<section id='extended' class='" . $this->h5ai->getView() . "-view clearfix'>\n";
|
||||
$html .= "<ul>\n";
|
||||
$html .= $this->generateHeaders();
|
||||
if ( $this->parent !== null ) {
|
||||
$html .= $this->parent->toHtml( $this->h5ai->getDateFormat() );
|
||||
}
|
||||
foreach( $this->content as $entry ) {
|
||||
$html .= $entry->toHtml( $this->h5ai->getDateFormat() );
|
||||
}
|
||||
$html .= "</ul>\n";
|
||||
if ( count( $this->content ) === 0 ) {
|
||||
$html .= "<div class='empty l10n-empty'>empty</div>";
|
||||
}
|
||||
$html .="</section>";
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function generateHeaders() {
|
||||
|
||||
$asc = "<img src='/h5ai/images/ascending.png' class='sort' alt='ascending' />";
|
||||
$desc = "<img src='/h5ai/images/descending.png' class='sort' alt='descending' />";
|
||||
|
||||
$so = $this->h5ai->getSortOrder();
|
||||
$order = $so["ascending"] ? $asc : $desc;
|
||||
$nameHref = "?col=name" . ( $so["column"] === "name" && $so["ascending"] ? "&asc=false" : "&asc=true" );
|
||||
$dateHref = "?col=date" . ( $so["column"] === "date" && $so["ascending"] ? "&asc=false" : "&asc=true" );
|
||||
$sizeHref = "?col=size" . ( $so["column"] === "size" && $so["ascending"] ? "&asc=false" : "&asc=true" );
|
||||
$nameSort = $so["column"] === "name" ? $order : "";
|
||||
$dateSort = $so["column"] === "date" ? $order : "";
|
||||
$sizeSort = $so["column"] === "size" ? $order : "";
|
||||
|
||||
$html = "\t<li class='header'>\n";
|
||||
$html .= "\t\t<a class='icon'></a>\n";
|
||||
$html .= "\t\t<a class='label' href='$nameHref'><span class='l10n-name'>Name</span>$nameSort</a>\n";
|
||||
$html .= "\t\t<a class='date' href='$dateHref'>$dateSort<span class='l10n-lastModified'>Last modified</span></a>\n";
|
||||
$html .= "\t\t<a class='size' href='$sizeHref'>$sizeSort<span class='l10n-size'>Size</span></a>\n";
|
||||
$html .= "\t</li>\n";
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
263
src/h5ai/php/h5ai.php
Normal file
|
@ -0,0 +1,263 @@
|
|||
<?php
|
||||
|
||||
require_once "cache.php";
|
||||
|
||||
class H5ai {
|
||||
private static $SORT_ORDER = array( "column" => "name", "ascending" => true );
|
||||
private static $VIEWMODES = array( "details", "icons" );
|
||||
|
||||
private $docRoot, $domain, $options, $types, $cache, $absHref, $absPath, $ignore, $ignoreRE, $sortOrder, $dateFormat, $view;
|
||||
|
||||
public function __construct() {
|
||||
|
||||
$this->docRoot = getenv( "DOCUMENT_ROOT" );
|
||||
$this->domain = getenv( "HTTP_HOST" );
|
||||
|
||||
$this->options = $this->loadOptions( $this->docRoot . "/h5ai/options.js" );
|
||||
$this->types = $this->loadTypes( $this->docRoot . "/h5ai/types.txt" );
|
||||
$this->cache = new Cache( $this->docRoot . "/h5ai/cache" );
|
||||
|
||||
$this->absHref = $this->normalizePath( preg_replace( '/\\?.*/', '', getenv( "REQUEST_URI" ) ), true );
|
||||
$this->absPath = $this->normalizePath( $this->docRoot . rawurldecode( $this->absHref ), false );
|
||||
|
||||
$this->ignore = $this->options["options"]["ignore"];
|
||||
$this->ignoreRE = $this->options["options"]["ignoreRE"];
|
||||
$this->sortOrder = array(
|
||||
"column" => array_key_exists( "col", $_REQUEST ) ? $_REQUEST["col"] : H5ai::$SORT_ORDER["column"],
|
||||
"ascending" => array_key_exists( "asc", $_REQUEST ) ? $_REQUEST["asc"] !== "false" : H5ai::$SORT_ORDER["ascending"]
|
||||
);
|
||||
$this->dateFormat = $this->options["options"]["dateFormat"];
|
||||
$this->view = array_key_exists( "view", $_REQUEST ) ? $_REQUEST["view"] : $this->options["options"]["viewmodes"][0];
|
||||
if ( !in_array( $this->view, H5ai::$VIEWMODES ) ) {
|
||||
$this->view = H5ai::$VIEWMODES[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function loadOptions( $file ) {
|
||||
|
||||
$str = file_exists( $file ) ? file_get_contents( $file ) : "";
|
||||
$str = preg_replace( "/\/\*.*?\*\//s", "", $str );
|
||||
|
||||
$optstr = preg_replace( "/^.*h5aiOptions\s*=\s*/s", "", $str );
|
||||
$optstr = preg_replace( "/;.*/s", "", $optstr );
|
||||
$options = json_decode( $optstr, true );
|
||||
|
||||
$langstr = preg_replace( "/^.*h5aiLangs\s*=\s*/s", "", $str );
|
||||
$langstr = preg_replace( "/;.*/s", "", $langstr );
|
||||
$langs = json_decode( $langstr, true );
|
||||
|
||||
return array( "options" => $options, "langs" => $langs );
|
||||
}
|
||||
|
||||
|
||||
private function loadTypes( $file ) {
|
||||
|
||||
$lines = file( $file );
|
||||
$types = array();
|
||||
foreach( $lines as $line ) {
|
||||
if ( substr( $line, 0, 1 ) === '#' ) {
|
||||
continue;
|
||||
}
|
||||
$types[] = preg_split( "/\s+/", $line );
|
||||
}
|
||||
return $types;
|
||||
}
|
||||
|
||||
public function getDocRoot() {
|
||||
|
||||
return $this->docRoot;
|
||||
}
|
||||
|
||||
public function getDomain() {
|
||||
|
||||
return $this->domain;
|
||||
}
|
||||
|
||||
public function getView() {
|
||||
|
||||
return $this->view;
|
||||
}
|
||||
|
||||
public function getOptions() {
|
||||
|
||||
return $this->options["options"] ;
|
||||
}
|
||||
|
||||
public function getLangs() {
|
||||
|
||||
return $this->options["langs"];
|
||||
}
|
||||
|
||||
public function getAbsHref( $absPath = null, $endWithSlash = true ) {
|
||||
|
||||
if ( $absPath === null ) {
|
||||
return $this->absHref;
|
||||
}
|
||||
return $this->normalizePath( rawurlencode( preg_replace( "!^" . $this->docRoot . "!", "", $absPath ) ), $endWithSlash );
|
||||
}
|
||||
|
||||
public function getAbsPath( $absHref = null ) {
|
||||
|
||||
if ( $absHref === null ) {
|
||||
return $this->absPath;
|
||||
}
|
||||
return $this->normalizePath( $this->docRoot . rawurldecode( $absHref ), false );
|
||||
}
|
||||
|
||||
public function getSortOrder() {
|
||||
|
||||
return $this->sortOrder;
|
||||
}
|
||||
|
||||
public function getDateFormat() {
|
||||
|
||||
return $this->dateFormat;
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
|
||||
$title = $this->domain . rawurldecode( $this->absHref );
|
||||
$title = preg_replace( "/\/$/", "", $title );
|
||||
$title = preg_replace( "/\//", " > ", $title );
|
||||
if ( $this->absHref !== "/" ) {
|
||||
$title = basename( $this->absPath ) . " - " . $title;
|
||||
}
|
||||
return $title;
|
||||
}
|
||||
|
||||
public function getType( $absPath ) {
|
||||
|
||||
foreach( $this->types as $type ) {
|
||||
foreach( array_slice( $type, 1 ) as $pattern ) {
|
||||
if ( $this->endsWith( $absPath, $pattern ) ) {
|
||||
return $type[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
public function ignoreThisFile( $file ) {
|
||||
|
||||
# always ignore
|
||||
if ( $file === "." || $file === ".." || $this->startsWith( $file, '.ht' ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( in_array( $file, $this->ignore ) ) {
|
||||
return true;
|
||||
}
|
||||
foreach ( $this->ignoreRE as $re ) {
|
||||
if ( preg_match( $re, $file ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function readDir( $path ) {
|
||||
|
||||
$content = array();
|
||||
if ( is_dir( $path ) ) {
|
||||
if ( $dir = opendir( $path ) ) {
|
||||
while ( ( $file = readdir( $dir ) ) !== false ) {
|
||||
if ( ! $this->ignoreThisFile( $file ) ) {
|
||||
$content[] = $file;
|
||||
}
|
||||
}
|
||||
closedir( $dir );
|
||||
}
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function getLabel( $absHref ) {
|
||||
|
||||
return $absHref === "/" ? $this->domain : rawurldecode( basename( $absHref ) );
|
||||
}
|
||||
|
||||
public function normalizePath( $path, $endWithSlash ) {
|
||||
|
||||
return ( $path === "/" ) ? "/" : ( preg_replace( '#/$#', '', $path ) . ( $endWithSlash ? "/" : "" ) );
|
||||
}
|
||||
|
||||
public function startsWith( $sequence, $start ) {
|
||||
|
||||
return substr( $sequence, 0, strlen( $start ) ) === $start;
|
||||
}
|
||||
|
||||
public function endsWith( $sequence, $end ) {
|
||||
|
||||
return substr( $sequence, -strlen( $end ) ) === $end;
|
||||
}
|
||||
|
||||
public function getHttpCode( $absHref ) {
|
||||
|
||||
return $this->cachedHttpCode( $absHref );
|
||||
#return $this->fetchHttpCode( $absHref );
|
||||
#return $this->guessHttpCode( $absHref );
|
||||
}
|
||||
|
||||
public function cachedHttpCode( $absHref ) {
|
||||
|
||||
$cached = $this->cache->get( $absHref );
|
||||
if ( $cached === false ) {
|
||||
$folderStatus = $this->options["options"]["folderStatus"];
|
||||
if ( array_key_exists( $absHref, $folderStatus ) ) {
|
||||
$code = $folderStatus[$absHref];
|
||||
} else {
|
||||
$code = $this->fetchHttpCode( $absHref );
|
||||
}
|
||||
$cached = array( "href" => $absHref, "code" => $code );
|
||||
$this->cache->set( $absHref, $cached );
|
||||
}
|
||||
return $cached["code"];
|
||||
}
|
||||
|
||||
public function fetchHttpCode( $absHref ) {
|
||||
|
||||
$contentType = "Content-Type:";
|
||||
$h5aiContentType = "Content-Type: text/html;h5ai=";
|
||||
$host = getenv( "HTTP_HOST" );
|
||||
$port = getenv( "SERVER_PORT" );
|
||||
$msg = "HEAD $absHref HTTP/1.1\r\nHost: $host\r\nConnection: Close\r\n\r\n";
|
||||
|
||||
$errno = "";
|
||||
$errstr = "";
|
||||
$socket = fsockopen( $host, $port, $errno, $errstr, 30 );
|
||||
if( $socket === 0 ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
fwrite( $socket, $msg );
|
||||
$content = fgets( $socket );
|
||||
$code = intval( trim( substr( $content, 9, 4 ) ) );
|
||||
if ( $code === 200 ) {
|
||||
while ( ! $this->startsWith( $content, $contentType ) ) {
|
||||
$content = fgets( $socket );
|
||||
}
|
||||
if ( $this->startsWith( $content, $h5aiContentType ) ) {
|
||||
$code = "h5ai";
|
||||
}
|
||||
}
|
||||
fclose( $socket );
|
||||
return $code;
|
||||
}
|
||||
|
||||
public function guessHttpCode( $absHref ) {
|
||||
|
||||
$indexFiles = array( "index.html", "index.cgi", "index.pl", "index.php", "index.xhtml", "index.htm" );
|
||||
$absPath = $this->getAbsPath( $absHref );
|
||||
$files = $this->readDir( $absPath );
|
||||
foreach ( $files as $file ) {
|
||||
if ( in_array( $file, $indexFiles ) ) {
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
return "h5ai";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
23
src/h5ai/php/httpcode.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
require_once "h5ai.php";
|
||||
|
||||
function getHttpCodes( $h5ai, $hrefs ) {
|
||||
|
||||
$codes = array();
|
||||
foreach ( $hrefs as $href ) {
|
||||
$href = trim( $href );
|
||||
if ( strlen( $href ) > 0 ) {
|
||||
$codes[$href] = $h5ai->getHttpCode( $href );
|
||||
}
|
||||
}
|
||||
return $codes;
|
||||
}
|
||||
|
||||
$h5ai = new H5ai();
|
||||
$hrefs = preg_split( "/;/", array_key_exists( "hrefs", $_REQUEST ) ? $_REQUEST[ "hrefs" ] : "" );
|
||||
$codes = getHttpCodes( $h5ai, $hrefs );
|
||||
|
||||
echo count( $codes ) === 0 ? "{}" : json_encode( $codes );
|
||||
|
||||
?>
|
15
src/h5ai/php/main.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
require_once "h5ai.php";
|
||||
require_once "crumb.php";
|
||||
require_once "customize.php";
|
||||
require_once "extended.php";
|
||||
require_once "tree.php";
|
||||
|
||||
$h5ai = new H5ai();
|
||||
$crumb = new Crumb( $h5ai );
|
||||
$customize = new Customize( $h5ai );
|
||||
$extended = new Extended( $h5ai );
|
||||
$tree = new Tree( $h5ai );
|
||||
|
||||
?>
|
147
src/h5ai/php/tree.php
Normal file
|
@ -0,0 +1,147 @@
|
|||
<?php
|
||||
|
||||
class TreeEntry {
|
||||
private $h5ai, $label, $absPath, $absHref, $isFolder, $type, $content;
|
||||
|
||||
public function __construct( $h5ai, $absPath, $absHref, $type = null ) {
|
||||
|
||||
$this->h5ai = $h5ai;
|
||||
|
||||
$this->label = $this->h5ai->getLabel( $absHref );
|
||||
$this->absPath = $this->h5ai->normalizePath( $absPath, false );
|
||||
$this->isFolder = is_dir( $this->absPath );
|
||||
$this->absHref = $this->h5ai->normalizePath( $absHref, $this->isFolder );
|
||||
|
||||
$this->type = $type !== null ? $type : ( $this->isFolder ? "folder" : $this->h5ai->getType( $this->absPath ) );
|
||||
$this->content = null;
|
||||
}
|
||||
|
||||
public function loadContent() {
|
||||
|
||||
$this->content = array();
|
||||
|
||||
if ( $this->h5ai->getHttpCode( $this->absHref ) !== "h5ai" ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$files = $this->h5ai->readDir( $this->absPath );
|
||||
foreach ( $files as $file ) {
|
||||
$tree = new TreeEntry( $this->h5ai, $this->absPath . "/" . $file, $this->absHref . rawurlencode( $file ) );
|
||||
|
||||
if ( $tree->isFolder ) {
|
||||
$this->content[$tree->absPath] = $tree;
|
||||
}
|
||||
}
|
||||
|
||||
$this->sort();
|
||||
}
|
||||
|
||||
public function cmpTrees( $t1, $t2 ) {
|
||||
|
||||
if ( $t1->isFolder && !$t2->isFolder ) {
|
||||
return -1;
|
||||
}
|
||||
if ( !$t1->isFolder && $t2->isFolder ) {
|
||||
return 1;
|
||||
}
|
||||
return strcasecmp( $t1->absPath, $t2->absPath );
|
||||
}
|
||||
|
||||
public function sort() {
|
||||
|
||||
if ( $this->content !== null ) {
|
||||
uasort( $this->content, array( $this, "cmpTrees" ) );
|
||||
}
|
||||
}
|
||||
|
||||
public function toHtml() {
|
||||
|
||||
$classes = "entry " . $this->type . ( $this->absHref === $this->h5ai->getAbsHref() ? " current" : "" );
|
||||
$img = $this->type;
|
||||
if ( $this->absHref === "/" ) {
|
||||
$img = "folder-home";
|
||||
}
|
||||
$hint = "";
|
||||
$code = "h5ai";
|
||||
|
||||
if ( $this->isFolder ) {
|
||||
$code = $this->h5ai->getHttpCode( $this->absHref );
|
||||
$classes .= " checkedHttpCode";
|
||||
if ( $code !== "h5ai" ) {
|
||||
if ( $code === 200 ) {
|
||||
$img = "folder-page";
|
||||
$hint = "<span class='hint'><img src='/h5ai/images/page.png' alt='page' /></span>";
|
||||
} else {
|
||||
$classes .= " error";
|
||||
$hint = "<span class='hint'> " . $code . " </span>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$html = "<div class='" . $classes ."'>\n";
|
||||
if ( $this->content !== null && count( $this->content ) === 0 || $code !== "h5ai" ) {
|
||||
$html .= "<span class='blank'></span>\n";
|
||||
} else {
|
||||
$indicatorState = $this->content === null ? " unknown" : " open";
|
||||
$html .= "<span class='indicator" . $indicatorState . "'><img src='/h5ai/images/tree.png' alt='>' /></span>\n";
|
||||
}
|
||||
$html .= "<a href='" . $this->absHref . "'>\n";
|
||||
$html .= "<span class='icon'><img src='/h5ai/icons/16x16/" . $img . ".png' alt='" . $img . "' /></span>\n";
|
||||
$html .= "<span class='label'>" . $this->label . "</span>" . $hint . "\n";
|
||||
$html .= "</a>\n";
|
||||
$html .= $this->contentToHtml();
|
||||
$html .= "</div>\n";
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function contentToHtml() {
|
||||
|
||||
$html = "<ul class='content'>\n";
|
||||
if ( $this->content !== null ) {
|
||||
foreach( $this->content as $tree ) {
|
||||
$html .= "<li>" . $tree->toHtml() . "</li>";
|
||||
}
|
||||
}
|
||||
$html .= "</ul>\n";
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function getRoot() {
|
||||
|
||||
if ( $this->absHref === "/" ) {
|
||||
return $this;
|
||||
};
|
||||
|
||||
$tree = new TreeEntry( $this->h5ai, dirname( $this->absPath ), dirname( $this->absHref ) );
|
||||
$tree->loadContent();
|
||||
$tree->content[ $this->absPath ] = $this;
|
||||
|
||||
return $tree->getRoot();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Tree {
|
||||
private $h5ai;
|
||||
|
||||
public function __construct( $h5ai ) {
|
||||
|
||||
$this->h5ai = $h5ai;
|
||||
}
|
||||
|
||||
public function toHtml() {
|
||||
|
||||
$options = $this->h5ai->getOptions();
|
||||
if ( $options["showTree"] === false ) {
|
||||
return "";
|
||||
}
|
||||
|
||||
$tree = new TreeEntry( $this->h5ai, $this->h5ai->getAbsPath(), $this->h5ai->getAbsHref() );
|
||||
$tree->loadContent();
|
||||
$root = $tree->getRoot();
|
||||
return "<section id='tree'>\n" . $root->toHtml() . "</section>\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
20
src/h5ai/php/treecontent.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
if ( ! array_key_exists( "href", $_REQUEST ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once "h5ai.php";
|
||||
require_once "tree.php";
|
||||
|
||||
$h5ai = new H5ai();
|
||||
|
||||
$absHref = trim( $_REQUEST[ "href" ] );
|
||||
$absPath = $h5ai->getAbsPath( $absHref );
|
||||
|
||||
$tree = new TreeEntry( $h5ai, $absPath, $absHref );
|
||||
$tree->loadContent();
|
||||
|
||||
echo $tree->contentToHtml();
|
||||
|
||||
?>
|
63
src/h5ai/types.txt
Normal file
|
@ -0,0 +1,63 @@
|
|||
archive .tar.gz .tgz .tar.bz2
|
||||
audio .mp3 .wav .ogg
|
||||
authors AUTHORS authors
|
||||
bin .so .o .class
|
||||
blank
|
||||
bmp .bmp
|
||||
c .c
|
||||
calc
|
||||
cd .iso .cue
|
||||
copying COPYING copying LICENSE license
|
||||
cpp .cpp
|
||||
css .css .less
|
||||
deb .deb
|
||||
default
|
||||
doc .doc
|
||||
draw
|
||||
eps
|
||||
exe .exe
|
||||
folder
|
||||
folder-home
|
||||
folder-open
|
||||
folder-page
|
||||
folder-parent
|
||||
gif .gif
|
||||
gzip .gz
|
||||
h .h
|
||||
hpp .hpp
|
||||
html .html .htm .shtml
|
||||
ico .ico
|
||||
image .xpm
|
||||
install INSTALL install
|
||||
java .java
|
||||
jpg .jpg .jpeg
|
||||
js .js .json
|
||||
log .log CHANGELOG changelog LOG log
|
||||
makefile .pom pom.xml build.xml
|
||||
package
|
||||
pdf .pdf
|
||||
php .php
|
||||
playlist .m3u
|
||||
png .png
|
||||
pres
|
||||
psd
|
||||
py .py
|
||||
rar .rar
|
||||
rb .rb
|
||||
readme README readme
|
||||
rpm .rpm
|
||||
rss .rss
|
||||
rtf .rtf
|
||||
script .conf .ini .sh .shar .csh .ksh .tcl
|
||||
source
|
||||
sql
|
||||
tar .tar
|
||||
tex .tex
|
||||
text .txt .text .md .markdown
|
||||
tiff .tiff
|
||||
unknown
|
||||
vcal .vcal
|
||||
video
|
||||
xml .xml
|
||||
zip .zip .Z .z .jar .war .bz2
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
################################
|
||||
# %BUILD_NAME% %BUILD_VERSION%
|
||||
# %BUILD_NAME% %BUILD_VERSION% (js)
|
||||
# customized .htaccess
|
||||
################################
|
||||
|
||||
|
@ -8,23 +8,6 @@
|
|||
# Options +FollowSymLinks
|
||||
|
||||
|
||||
<IfModule headers_module>
|
||||
|
||||
################################
|
||||
# cache images for 52 weeks
|
||||
################################
|
||||
|
||||
<FilesMatch "\.png$">
|
||||
Header set Cache-Control "max-age=31449600, public"
|
||||
</FilesMatch>
|
||||
|
||||
</IfModule>
|
||||
|
||||
|
||||
################################
|
||||
# style auto index
|
||||
################################
|
||||
|
||||
################################
|
||||
# IMPORTANT FOR XAMPP
|
||||
# if you're running XAMPP you might need to replace the
|
||||
|
@ -33,13 +16,6 @@
|
|||
################################
|
||||
<IfModule autoindex_module>
|
||||
|
||||
################################
|
||||
# uncomment the following line to force directory listing
|
||||
# even for directories with valid index files
|
||||
################################
|
||||
|
||||
# DirectoryIndex IGNORE-DEFAULT-INDEX-FILES
|
||||
|
||||
|
||||
################################
|
||||
# h5ai header and footer
|
||||
|
@ -81,7 +57,7 @@
|
|||
# icon mapping
|
||||
################################
|
||||
|
||||
AddIcon /h5ai/icons/16x16/parent.png ..
|
||||
AddIcon /h5ai/icons/16x16/folder-parent.png ..
|
||||
AddIcon /h5ai/icons/16x16/folder.png ^^DIRECTORY^^
|
||||
AddIcon /h5ai/icons/16x16/blank.png ^^BLANKICON^^
|
||||
|
||||
|
@ -144,3 +120,4 @@
|
|||
|
||||
</IfModule>
|
||||
|
||||
|
29
src/php.htaccess
Normal file
|
@ -0,0 +1,29 @@
|
|||
################################
|
||||
# %BUILD_NAME% %BUILD_VERSION% (php)
|
||||
# customized .htaccess
|
||||
################################
|
||||
|
||||
|
||||
# Options +Indexes
|
||||
# Options +FollowSymLinks
|
||||
|
||||
|
||||
################################
|
||||
# IMPORTANT FOR XAMPP
|
||||
# if you're running XAMPP you might need to replace the
|
||||
# following line with
|
||||
# <IfModule autoindex_color_module>
|
||||
################################
|
||||
<IfModule autoindex_module>
|
||||
|
||||
HeaderName /h5ai/header.php
|
||||
ReadmeName /h5ai/footer.php
|
||||
|
||||
IndexIgnore *
|
||||
|
||||
IndexOptions Type=text/html;h5ai=%BUILD_VERSION%
|
||||
IndexOptions Charset=UTF-8
|
||||
IndexOptions SuppressHTMLPreamble
|
||||
|
||||
</IfModule>
|
||||
|