1
0
mirror of https://github.com/lrsjng/h5ai.git synced 2025-08-24 06:23:14 +02:00

Added selection and zipped download.

This commit is contained in:
Lars Jung
2011-09-04 21:18:19 +02:00
parent a371ee2afd
commit 2d3b0eed4f
44 changed files with 3865 additions and 3000 deletions

View File

@@ -10,6 +10,12 @@ It uses the [Faenza icon set](http://tiheum.deviantart.com/art/Faenza-Icons-1733
## Changelog ## Changelog
### v0.15 · *2011-09-04*
* added zipped download for selected files
* cleaned and refactored
### v0.14.1 · *2011-09-01* ### v0.14.1 · *2011-09-01*
* display meta information in bottom bar (icon view) * display meta information in bottom bar (icon view)

View File

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

126
build.xml
View File

@@ -1,81 +1,81 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<project <project
name="h5ai" name="h5ai"
basedir="." basedir="."
default="release" default="release"
xmlns:scripp="antlib:de.larsjung.scripp.ant" xmlns:scripp="antlib:de.larsjung.scripp.ant"
> >
<target name="init"> <target name="init">
<property file="build.properties" /> <property file="build.properties" />
<tstamp> <tstamp>
<format property="build.stamp" pattern="yyyy-MM-dd-HHmmss" /> <format property="build.stamp" pattern="yyyy-MM-dd-HHmmss" />
</tstamp> </tstamp>
<property name="build.label" value="${project.name} ${project.version} b${build.stamp}" /> <property name="build.label" value="${project.name} ${project.version} b${build.stamp}" />
<echo>Build: ${build.label}</echo> <echo>Build: ${build.label}</echo>
<taskdef <taskdef
resource="de/larsjung/scripp/ant/antlib.xml" resource="de/larsjung/scripp/ant/antlib.xml"
uri="antlib:de.larsjung.scripp.ant" uri="antlib:de.larsjung.scripp.ant"
classpath="${lib.scripp.jar}" classpath="${lib.scripp.jar}"
/> />
</target> </target>
<target name="clean" depends="init"> <target name="clean" depends="init">
<delete dir="${build.dir}" /> <delete dir="${build.dir}" />
<delete dir="${release.dir}" /> <delete dir="${release.dir}" />
</target> </target>
<target name="build-prepare" depends="clean"> <target name="build-prepare" depends="clean">
<mkdir dir="${build.dir}" /> <mkdir dir="${build.dir}" />
<copy todir="${build.dir}"> <copy todir="${build.dir}">
<fileset dir="${src.dir}" /> <fileset dir="${src.dir}" />
<fileset file="LICENSE.txt" /> <fileset file="LICENSE.txt" />
<fileset file="README.md" /> <fileset file="README.md" />
</copy> </copy>
<replace dir="${build.dir}"> <replace dir="${build.dir}">
<replacefilter token="%BUILD%" value="${build.label}" /> <replacefilter token="%BUILD%" value="${build.label}" />
<replacefilter token="%BUILD_NAME%" value="${project.name}" /> <replacefilter token="%BUILD_NAME%" value="${project.name}" />
<replacefilter token="%BUILD_VERSION%" value="${project.version}" /> <replacefilter token="%BUILD_VERSION%" value="${project.version}" />
<replacefilter token="%BUILD_STAMP%" value="${build.stamp}" /> <replacefilter token="%BUILD_STAMP%" value="${build.stamp}" />
</replace> </replace>
</target> </target>
<target name="build" depends="build-prepare"> <target name="build" depends="build-prepare">
<scripp.dir dir="${build.dir}/h5ai/css" /> <scripp.dir dir="${build.dir}/h5ai/css" />
<scripp.dir dir="${build.dir}/h5ai/js" /> <scripp.dir dir="${build.dir}/h5ai/js" />
</target> </target>
<target name="build-uncompressed" depends="build-prepare"> <target name="build-uncompressed" depends="build-prepare">
<scripp.dir dir="${build.dir}/h5ai/css" compress="false" /> <scripp.dir dir="${build.dir}/h5ai/css" compress="false" />
<scripp.dir dir="${build.dir}/h5ai/js" compress="false" /> <scripp.dir dir="${build.dir}/h5ai/js" compress="false" />
</target> </target>
<target name="release" depends="build"> <target name="release" depends="build">
<mkdir dir="${release.dir}" /> <mkdir dir="${release.dir}" />
<zip destfile="${release.dir}/${project.name}-${project.version}.zip" basedir="${build.dir}" /> <zip destfile="${release.dir}/${project.name}-${project.version}.zip" basedir="${build.dir}" />
<tar destfile="${release.dir}/${project.name}-${project.version}.tar" basedir="${build.dir}"/> <tar destfile="${release.dir}/${project.name}-${project.version}.tar" basedir="${build.dir}"/>
<gzip destfile="${release.dir}/${project.name}-${project.version}.tar.gz" src="${release.dir}/${project.name}-${project.version}.tar"/> <gzip destfile="${release.dir}/${project.name}-${project.version}.tar.gz" src="${release.dir}/${project.name}-${project.version}.tar"/>
<delete file="${release.dir}/${project.name}-${project.version}.tar" /> <delete file="${release.dir}/${project.name}-${project.version}.tar" />
</target> </target>
<macrodef name="scripp.dir"> <macrodef name="scripp.dir">
<attribute name="dir" /> <attribute name="dir" />
<attribute name="compress" default="true" /> <attribute name="compress" default="true" />
<sequential> <sequential>
<scripp:process compress="@{compress}"> <scripp:process compress="@{compress}">
<fileset dir="@{dir}" includes="**/*.less,**/*.css,**/*.js" excludes="inc/**/*,**/*.min.css,**/*.min.js" /> <fileset dir="@{dir}" includes="**/*.less,**/*.css,**/*.js" excludes="inc/**/*,**/*.min.css,**/*.min.js" />
<globmapper from="*.less" to="*.css" /> <globmapper from="*.less" to="*.css" />
<globmapper from="*.css" to="*.css" /> <globmapper from="*.css" to="*.css" />
<globmapper from="*.js" to="*.js" /> <globmapper from="*.js" to="*.js" />
</scripp:process> </scripp:process>
<delete dir="@{dir}/inc"> <delete dir="@{dir}/inc">
<fileset dir="@{dir}" includes="**/*.less" /> <fileset dir="@{dir}" includes="**/*.less" />
</delete> </delete>
</sequential> </sequential>
</macrodef> </macrodef>
</project> </project>

Binary file not shown.

BIN
release/h5ai-0.15.tar.gz Normal file

Binary file not shown.

View File

@@ -19,17 +19,17 @@ AddType text/html .php
# cache images, css and js for 52 weeks # cache images, css and js for 52 weeks
<IfModule headers_module> <IfModule headers_module>
<FilesMatch "\.png$"> <FilesMatch "\.png$">
Header set Cache-Control "max-age=31449600, public" Header set Cache-Control "max-age=31449600, public"
</FilesMatch> </FilesMatch>
<FilesMatch "\.css$"> <FilesMatch "\.css$">
Header set Cache-Control "max-age=31449600, public" Header set Cache-Control "max-age=31449600, public"
</FilesMatch> </FilesMatch>
<FilesMatch "\.js$"> <FilesMatch "\.js$">
Header set Cache-Control "max-age=31449600, public" Header set Cache-Control "max-age=31449600, public"
</FilesMatch> </FilesMatch>
<FilesMatch "thumb-.*\.jpg$"> <FilesMatch "thumb-.*\.jpg$">
Header set Cache-Control "max-age=31449600, public" Header set Cache-Control "max-age=31449600, public"
</FilesMatch> </FilesMatch>
</IfModule> </IfModule>

View File

@@ -1,246 +1,265 @@
#extended.details-view { #extended.details-view {
display: none; display: none;
ul { ul {
margin: 0; margin: 0;
padding: 0; padding: 0;
list-style: none; list-style: none;
li { li {
position: relative; position: relative;
white-space: nowrap; white-space: nowrap;
clear: both; clear: both;
&.header { &.header {
a, a:active, a:visited { a, a:active, a:visited {
padding-bottom: 18px; padding-bottom: 18px;
color: #555; color: #555;
text-decoration: none; text-decoration: none;
opacity: 0.4; opacity: 0.4;
cursor: pointer; cursor: pointer;
.transition( all 0.2s ease-in-out ); .transition(all 0.2s ease-in-out);
&:hover { &:hover {
color: #555; color: #555;
opacity: 0.9; opacity: 0.9;
} }
img { img {
width: 12px; width: 12px;
height: 12px; height: 12px;
padding: 0 8px; padding: 0 8px;
} }
} }
} }
&.entry { &.entry {
border-bottom: 1px solid #ddd;
a, a:active, a:visited { a, a:active, a:visited {
display: block; display: block;
color: #555; color: #555;
text-decoration: none; text-decoration: none;
cursor: pointer; cursor: pointer;
border-bottom: 1px solid #ddd;
&:hover, &.hover { &:hover, &.hover {
background-color: #f6f6f6; background-color: #f6f6f6;
color: #e80; color: #e80;
} }
} &.selected {
&.error { border-color: rgba(240,100,0,0.2);
a, a:active, a:visited { background-color: rgba(240,100,0,0.2);
color: #aaa; }
}
&.error {
a, a:active, a:visited {
color: #aaa;
.label { .label {
.hint { .hint {
margin-left: 12px; margin-left: 12px;
font-size: 0.9em; font-size: 0.9em;
color: #c55; color: #c55;
} }
} }
&:hover, &.hover { &:hover, &.hover {
opacity: 1; opacity: 1;
background-color: #f6f6f6; background-color: #f6f6f6;
color: #e80; color: #e80;
} }
} }
} }
&.folder-parent { &.folder-parent {
.date, .size { .date, .size {
display: none; display: none;
} }
} }
&.folder { &.folder {
.size { .size {
display: none; display: none;
} }
} }
} }
.icon, .label, .date, .size { .icon, .label, .date, .size {
padding: 6px; padding: 6px;
} }
.icon { .icon {
display: inline-block; display: inline-block;
position: absolute; position: absolute;
left: 0; left: 0;
top: 2px; top: 2px;
width: 16px; width: 16px;
img { img {
width: 16px; width: 16px;
height: 16px; height: 16px;
} }
} }
.icon.big { .icon.big {
display: none; display: none;
} }
.label { .label {
display: block; display: block;
margin: 0 270px 0 24px; margin: 0 270px 0 24px;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-align: left; text-align: left;
} }
.date { .date {
position: absolute; position: absolute;
right: 100px; right: 100px;
top: 0; top: 0;
text-align: right; text-align: right;
width: 160px; width: 160px;
white-space: nowrap; white-space: nowrap;
} }
.size { .size {
position: absolute; position: absolute;
right: 0; right: 0;
top: 0; top: 0;
text-align: right; text-align: right;
width: 80px; width: 80px;
white-space: nowrap; white-space: nowrap;
} }
&.entry.thumb .icon.small { &.entry.thumb .icon.small {
overflow: hidden; overflow: hidden;
padding: 5px; padding: 5px;
img { img {
background-color: #eee; background-color: #eee;
width: 16px; width: 16px;
height: 16px; height: 16px;
border: 1px solid #ddd; border: 1px solid #ddd;
overflow: hidden; overflow: hidden;
} }
} }
} }
} }
.empty { .empty {
text-align: center; text-align: center;
margin: 50px 0; margin: 50px 0;
color: #ddd; color: #ddd;
font-size: 5em; font-size: 5em;
font-weight: bold; font-weight: bold;
} }
}
#selection-rect {
display: none;
position: absolute;
left: 0;
top: 0;
z-index: 2;
border: 1px dashed rgba(240,100,0,0.5);
background-color: rgba(240,100,0,0.2);
} }
#extended.icons-view { #extended.icons-view {
display: none; display: none;
padding: 3px; padding: 3px;
border: 1px solid #eee; border: 1px solid #eee;
border-radius: 15px; border-radius: 15px;
ul { ul {
margin: 0; margin: 0;
padding: 0; padding: 0;
list-style: none; list-style: none;
li { li {
&.header { &.header {
display: none; display: none;
} }
&.entry { &.entry {
float: left; float: left;
a, a:active, a:visited { a, a:active, a:visited {
display: block; display: block;
margin: 8px; margin: 8px;
padding: 8px; padding: 8px;
width: 100px; width: 100px;
height: 120px; height: 120px;
float: left; float: left;
text-align: center; text-align: center;
text-decoration: none; text-decoration: none;
overflow: hidden; overflow: hidden;
border-radius: 5px; border-radius: 5px;
color: #555; color: #555;
cursor: pointer; cursor: pointer;
border: 2px solid rgba(0,0,0,0); border: 2px solid rgba(0,0,0,0);
&:hover, &.hover { &:hover, &.hover {
color: #e80; color: #e80;
border-color: #eee; border-color: #eee;
background-color: #f6f6f6; background-color: #f6f6f6;
} }
.icon { &.selected {
display: block; border-color: rgba(240,100,0,0.2);
background-color: rgba(240,100,0,0.2);
}
.icon {
display: block;
img { img {
min-width: 48px; min-width: 48px;
min-height: 48px; min-height: 48px;
margin-bottom: 8px; margin-bottom: 8px;
} }
} }
.icon.small { .icon.small {
display: none; display: none;
} }
.label { .label {
display: block; display: block;
word-wrap: break-word; word-wrap: break-word;
} }
.date, .size { .date, .size {
display: none; display: none;
} }
} }
&.error { &.error {
a, a:active, a:visited { a, a:active, a:visited {
color: #aaa; color: #aaa;
text-decoration: none; text-decoration: none;
.label { .label {
.hint { .hint {
padding: 0 6px; padding: 0 6px;
font-size: 0.9em; font-size: 0.9em;
color: #c55; color: #c55;
} }
} }
&:hover, &.hover { &:hover, &.hover {
color: #e80; color: #e80;
border-color: #eee; border-color: #eee;
background-color: #f6f6f6; background-color: #f6f6f6;
} }
} }
} }
} }
&.entry.thumb .icon.big { &.entry.thumb .icon.big {
width: 100px; width: 100px;
height: 58px; height: 58px;
overflow: hidden; overflow: hidden;
img { img {
background-color: #eee; background-color: #eee;
min-width: 46px; min-width: 46px;
min-height: 46px; min-height: 46px;
min-width: 12px; min-width: 12px;
min-height: 12px; min-height: 12px;
border: 1px solid #ddd; border: 1px solid #ddd;
overflow: hidden; overflow: hidden;
} }
} }
} }
} }
.empty { .empty {
padding: 16px; padding: 16px;
height: 120px; height: 120px;
text-align: center; text-align: center;
color: #ddd; color: #ddd;
font-size: 5em; font-size: 5em;
font-weight: bold; font-weight: bold;
} }
} }

View File

@@ -4,108 +4,113 @@
html.js { html.js {
.hideOnJs { .hideOnJs {
display: none; display: none;
} }
} }
html.no-js { html.no-js {
.hideOnNoJs { .hideOnNoJs {
display: none; display: none;
} }
} }
body { body {
font-family: Ubuntu, sans-serif; font-family: Ubuntu, sans-serif;
font-size: 16px; font-size: 16px;
color: #555; color: #555;
margin: 80px 30px; margin: 80px 30px;
} }
body > nav { body > nav {
position: fixed; position: fixed;
z-index: 1; z-index: 1;
width: 100%; width: 100%;
left: 0; left: 0;
top: 0; top: 0;
font-size: 0.85em; font-size: 0.85em;
background-color: rgb(241,241,241); background-color: rgb(241,241,241);
border-bottom: 2px solid rgb(210,210,210); border-bottom: 2px solid rgb(210,210,210);
span.jsDisabledFallback { span.jsDisabledFallback {
display: block; display: block;
height: 30px; height: 30px;
line-height: 30px; line-height: 30px;
padding: 0 10px; padding: 0 10px;
color: #999; color: #999;
} }
a, a:active, a:visited { a, a:active, a:visited {
color: #555; color: #555;
cursor: pointer; cursor: pointer;
text-decoration: none; text-decoration: none;
opacity: 0.7; opacity: 0.7;
.transition( all 0.2s ease-in-out ); .transition(all 0.2s ease-in-out);
display: block; display: block;
height: 30px; height: 30px;
line-height: 30px; line-height: 30px;
padding: 0 10px; padding: 0 10px;
&:hover, &.hover { &:hover, &.hover {
color: #e80; color: #e80;
background-color: rgba(255,255,255,0.5); background-color: rgba(255,255,255,0.5);
opacity: 1.0; opacity: 1.0;
} }
} }
.current a { .current a {
background-color: rgba(255,255,255,0.5); background-color: rgba(255,255,255,0.5);
opacity: 1.0; opacity: 1.0;
} }
img { img {
width: 16px; width: 16px;
height: 16px; height: 16px;
vertical-align: bottom; vertical-align: bottom;
padding: 0 6px 6px 0; padding: 0 6px 6px 0;
} }
.crumb { .crumb {
float: left; float: left;
border-right: 1px solid rgb(231,231,231); border-right: 1px solid rgb(231,231,231);
.hint { .hint {
margin-left: 8px; margin-left: 8px;
font-style: italic; font-style: italic;
color: #999; color: #999;
} }
img.hint { img.hint {
width: 10px; width: 10px;
height: 10px; height: 10px;
vertical-align: baseline; vertical-align: baseline;
padding: 0px; padding: 0px;
} }
} }
.view { .view {
float: right; float: right;
border-left: 1px solid rgb(231,231,231); border-left: 1px solid rgb(231,231,231);
} }
#download {
display: none;
float: right;
border-left: 1px solid rgb(231,231,231);
}
} }
#content { #content {
max-width: 960px; max-width: 960px;
margin: 0 auto; margin: 0 auto;
> header { > header {
display: none; display: none;
padding-bottom: 10px; padding-bottom: 10px;
margin-bottom: 80px; margin-bottom: 80px;
border-bottom: 2px dashed #ddd; border-bottom: 2px dashed #ddd;
} }
> footer { > footer {
display: none; display: none;
padding-top: 10px; padding-top: 10px;
margin-top: 80px; margin-top: 80px;
border-top: 2px dashed #ddd; border-top: 2px dashed #ddd;
} }
} }
@@ -115,91 +120,91 @@ body > nav {
body > footer { body > footer {
position: fixed; position: fixed;
z-index: 1; z-index: 1;
width: 100%; width: 100%;
left: 0; left: 0;
bottom: 0; bottom: 0;
padding: 6px 0 8px 0; padding: 6px 0 8px 0;
background-color: rgb(241,241,241); background-color: rgb(241,241,241);
border-top: 2px solid rgb(210,210,210); border-top: 2px solid rgb(210,210,210);
color: #999; color: #999;
font-size: 0.85em; font-size: 0.85em;
text-align: center; text-align: center;
a, a:active, a:visited { a, a:active, a:visited {
color: #555; color: #555;
text-decoration: none; text-decoration: none;
.transition( all 0.2s ease-in-out ); .transition(all 0.2s ease-in-out);
opacity: 0.7; opacity: 0.7;
&:hover { &:hover {
color: #e80; color: #e80;
opacity: 1; opacity: 1;
} }
} }
.left { .left {
display: block; display: block;
padding: 0 8px; padding: 0 8px;
float: left float: left
} }
.center { .center {
display: block; display: block;
margin: 0 300px; margin: 0 300px;
} }
.right { .right {
display: block; display: block;
padding: 0 8px; padding: 0 8px;
float: right float: right
} }
.status { .status {
&.default { .sep {
} display: inline-block;
&.dynamic { padding: 0 6px;
display: none; }
span { &.default {
display: inline-block; }
padding: 0 6px; &.dynamic {
} display: none;
} }
} }
#langSelector { #langSelector {
position: relative; position: relative;
cursor: pointer; cursor: pointer;
.langOptions { .langOptions {
position: absolute; position: absolute;
z-index: 2; z-index: 2;
display: none; display: none;
right: 0; right: 0;
top: 0; top: 0;
background-color: rgb(241,241,241); background-color: rgb(241,241,241);
border: 1px solid rgb(210,210,210); border: 1px solid rgb(210,210,210);
ul { ul {
margin: 0; margin: 0;
padding: 0; padding: 0;
list-style: none; list-style: none;
text-align: left; text-align: left;
li { li {
padding: 8px 24px 10px 24px; padding: 8px 24px 10px 24px;
white-space: nowrap; white-space: nowrap;
border-top: 1px solid rgb(231,231,231); border-top: 1px solid rgb(231,231,231);
.transition( all 0.2s ease-in-out ); .transition(all 0.2s ease-in-out);
&.current { &.current {
color: #333; color: #333;
background-color: rgba(255,255,255,0.8); background-color: rgba(255,255,255,0.8);
} }
&:hover { &:hover {
color: #e80; color: #e80;
background-color: rgba(255,255,255,0.8); background-color: rgba(255,255,255,0.8);
} }
} }
} }
} }
} }
} }

View File

@@ -1,38 +1,38 @@
.border-radius ( @radius ) { .border-radius (@radius) {
-moz-border-radius: @radius; -moz-border-radius: @radius;
-webkit-border-radius: @radius; -webkit-border-radius: @radius;
border-radius: @radius; border-radius: @radius;
} }
.box-shadow ( @shadow ) { .box-shadow (@shadow) {
-moz-box-shadow: @shadow; -moz-box-shadow: @shadow;
-webkit-box-shadow: @shadow; -webkit-box-shadow: @shadow;
box-shadow: @shadow; box-shadow: @shadow;
} }
.transition ( @transition ) { .transition (@transition) {
-moz-transition: @transition; -moz-transition: @transition;
-ms-transition: @transition; -ms-transition: @transition;
-o-transition: @transition; -o-transition: @transition;
-webkit-transition: @transition; -webkit-transition: @transition;
transition: @transition; transition: @transition;
} }
.transform ( @transform ) { .transform (@transform) {
-moz-transform: @transform; -moz-transform: @transform;
-o-transform: @transform; -o-transform: @transform;
-webkit-transform: @transform; -webkit-transform: @transform;
transform: @transform; transform: @transform;
} }
.background-size ( @size ) { .background-size (@size) {
-moz-background-size: @size; -moz-background-size: @size;
-webkit-background-size: @size; -webkit-background-size: @size;
background-size: @size; background-size: @size;
} }

View File

@@ -1,68 +1,68 @@
#table { #table {
table { table {
display: block; display: block;
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
th, td { th, td {
padding: 3px 6px; padding: 3px 6px;
text-align: left; text-align: left;
border: none; border: none;
} }
th { th {
padding-bottom: 18px; padding-bottom: 18px;
opacity: 0.4; opacity: 0.4;
.transition( all 0.2s ease-in-out ); .transition(all 0.2s ease-in-out);
&:hover, &:hover a { &:hover, &:hover a {
color: #555; color: #555;
cursor: pointer; cursor: pointer;
opacity: 0.9; opacity: 0.9;
} }
a, a:visited { a, a:visited {
color: #555; color: #555;
font-weight: normal; font-weight: normal;
img { img {
width: 12px; width: 12px;
height: 12px; height: 12px;
padding: 0 8px; padding: 0 8px;
} }
} }
} }
td { td {
border: 1px solid #ddd; border: 1px solid #ddd;
border-left: none; border-left: none;
border-right: none; border-right: none;
} }
td:nth-child(1), th:nth-child(1) { td:nth-child(1), th:nth-child(1) {
text-align: center; text-align: center;
width: 16px; width: 16px;
img { img {
width: 16px; width: 16px;
height: 16px; height: 16px;
padding-top: 2px; padding-top: 2px;
} }
} }
td:nth-child(2), th:nth-child(2) { td:nth-child(2), th:nth-child(2) {
width: 682px; width: 682px;
max-width: 682px; max-width: 682px;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
} }
td:nth-child(3), th:nth-child(3) { td:nth-child(3), th:nth-child(3) {
text-align: right; text-align: right;
width: 160px; width: 160px;
min-width: 160px; min-width: 160px;
white-space: nowrap; white-space: nowrap;
} }
td:nth-child(4), th:nth-child(4) { td:nth-child(4), th:nth-child(4) {
text-align: right; text-align: right;
width: 70px; width: 70px;
min-width: 70px; min-width: 70px;
white-space: nowrap; white-space: nowrap;
} }
} }
} }

View File

@@ -1,129 +1,129 @@
#tree { #tree {
display: none; display: none;
position: fixed; position: fixed;
left: 0; left: 0;
top: 82px; top: 82px;
z-index: 1; z-index: 1;
overflow: auto; overflow: auto;
font-size: 0.85em; font-size: 0.85em;
padding: 16px 16px 16px 16px; padding: 16px 16px 16px 16px;
background-color: rgb(241,241,241); background-color: rgb(241,241,241);
border: 2px solid rgb(210,210,210); border: 2px solid rgb(210,210,210);
border-left: none; border-left: none;
.border-radius ( 0 15px 15px 0 ); .border-radius (0 15px 15px 0);
> .scrollbar { > .scrollbar {
margin: 12px 12px 12px 0; margin: 12px 12px 12px 0;
width: 6px; width: 6px;
background-color: rgb(210,210,210); background-color: rgb(210,210,210);
.border-radius( 3px ); .border-radius(3px);
.drag { .drag {
background-color: rgb(180,180,180); background-color: rgb(180,180,180);
.border-radius( 3px ); .border-radius(3px);
} }
&.dragOn .drag { &.dragOn .drag {
background-color: rgb(150,150,150); background-color: rgb(150,150,150);
} }
} }
.entry { .entry {
.blank, .indicator { .blank, .indicator {
display: inline-block; display: inline-block;
width: 16px; width: 16px;
height: 25px; height: 25px;
float: left; float: left;
} }
.indicator { .indicator {
opacity: 0.7; opacity: 0.7;
.transition( all 0.2s ease-in-out ); .transition(all 0.2s ease-in-out);
cursor: pointer; cursor: pointer;
&:hover { &:hover {
opacity: 1; opacity: 1;
} }
img { img {
position: relative; position: relative;
left: 0; left: 0;
top: 3px; top: 3px;
width: 12px; width: 12px;
height: 12px; height: 12px;
vertical-align: bottom; vertical-align: bottom;
.transition( all 0.2s ease-in-out ); .transition(all 0.2s ease-in-out);
} }
&.open { &.open {
img { img {
.transform( rotate(90deg) ); .transform(rotate(90deg));
} }
} }
&.unknown { &.unknown {
opacity: 0.3; opacity: 0.3;
} }
} }
> a, > a:active, > a.visited { > a, > a:active, > a.visited {
margin-left: 16px; margin-left: 16px;
padding: 4px 6px; padding: 4px 6px;
border: 1px solid rgba(0,0,0,0); border: 1px solid rgba(0,0,0,0);
.border-radius( 5px ); .border-radius(5px);
display: block; display: block;
color: #555; color: #555;
text-decoration: none; text-decoration: none;
opacity: 0.7; opacity: 0.7;
&:hover, &.hover { &:hover, &.hover {
color: #e80; color: #e80;
background-color: rgba(255,255,255,0.5); background-color: rgba(255,255,255,0.5);
opacity: 1; opacity: 1;
} }
.label { .label {
display: inline-block; display: inline-block;
} }
.icon { .icon {
display: inline-block; display: inline-block;
width: 20px; width: 20px;
img { img {
width: 16px; width: 16px;
height: 16px; height: 16px;
vertical-align: bottom; vertical-align: bottom;
} }
} }
.hint { .hint {
display: inline-block; display: inline-block;
margin-left: 12px; margin-left: 12px;
font-size: 0.9em; font-size: 0.9em;
color: #ccc; color: #ccc;
img { img {
width: 10px; width: 10px;
height: 10px; height: 10px;
vertical-align: baseline; vertical-align: baseline;
} }
} }
} }
&.file { &.file {
display: none; display: none;
} }
&.current { &.current {
> a, > a:active, > a:visited { > a, > a:active, > a:visited {
border: 1px solid rgb(221,221,221); border: 1px solid rgb(221,221,221);
background-color: rgba(255,255,255,0.5); background-color: rgba(255,255,255,0.5);
opacity: 1; opacity: 1;
} }
} }
&.error { &.error {
> a, > a:active, > a:visited { > a, > a:active, > a:visited {
color: #999; color: #999;
&:hover, &.hover { &:hover, &.hover {
color: #e80; color: #e80;
} }
} }
.hint { .hint {
color: #c55; color: #c55;
} }
} }
.content { .content {
list-style: none; list-style: none;
margin-left: 20px; margin-left: 20px;
} }
} }
} }

View File

@@ -3,13 +3,15 @@
#table { #table {
display: none; display: none;
} }
#tree, #content > header, #content > footer { #tree, #content > header, #content > footer {
display: block; display: block;
} }
html.no-js { html.no-js {
#extended.details-view, #extended.icons-view { #extended.details-view, #extended.icons-view {
display: block; display: block;
} }
} }

View File

@@ -1,34 +1,34 @@
<!-- generated code ends here --> <!-- generated code ends here -->
</section> </section>
<section id="extended"></section> <section id="extended" class="clearfix"></section>
<footer></footer> <footer></footer>
</section> </section>
<section id="tree"></section> <section id="tree"></section>
<footer class="clearfix"> <footer class="clearfix">
<span class="left"> <span class="left">
<a href="http://larsjung.de/h5ai" target="_blank" title="h5ai project page">h5ai %BUILD_VERSION% (js)</a> <a href="http://larsjung.de/h5ai" target="_blank" title="h5ai project page">h5ai %BUILD_VERSION% (js)</a>
</span> </span>
<span class="right"> <span class="right">
<span class="hideOnJs">JavaScript is disabled!</span> <span class="hideOnJs">JavaScript is disabled!</span>
<span id="langSelector"> <span id="langSelector">
<span class="lang">en</span> - <span class="l10n-lang">english</span> <span class="lang">en</span> - <span class="l10n-lang">english</span>
<span class="langOptions"></span> <span class="langOptions"></span>
</span> </span>
</span> </span>
<span class="center"> <span class="center">
<span class="hideOnNoJs"> <span class="hideOnNoJs">
<span class="status default"> <span class="status default">
<span class="folderCount"></span> <span class="l10n-folders">folders</span> <span class="folderCount"></span> <span class="l10n-folders">folders</span>
· <span class='sep'>·</span>
<span class="fileCount"></span> <span class="l10n-files">files</span> <span class="fileCount"></span> <span class="l10n-files">files</span>
</span> </span>
<span class="status dynamic"> <span class="status dynamic">
</span> </span>
</span> </span>
</span> </span>
</footer> </footer>
<script src="/h5ai/js/lib/jquery.min.js"></script> <script src="/h5ai/js/lib/jquery.min.js"></script>
<script src="/h5ai/options.js"></script> <script src="/h5ai/options.js"></script>
<script src="/h5ai/js/main-js.js"></script> <script src="/h5ai/js/main-js.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,4 +1,4 @@
<!-- generated code ends here --> <!-- generated code ends here -->
</section> </section>
</body> </body>
</html> </html>

View File

@@ -1,34 +1,38 @@
<!DOCTYPE html> <!DOCTYPE html>
<html class="no-js"> <html class="no-js">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Directory index · styled with h5ai</title> <title>Directory index · styled with h5ai</title>
<meta name="h5ai-version" content="h5ai %BUILD_VERSION% (js)"> <meta name="h5ai-version" content="h5ai %BUILD_VERSION% (js)">
<meta name="description" content="Directory index styled with h5ai (http://larsjung.de/h5ai)"> <meta name="description" content="Directory index styled with h5ai (http://larsjung.de/h5ai)">
<meta name="keywords" content="directory, index, autoindex, h5ai"> <meta name="keywords" content="directory, index, autoindex, h5ai">
<link rel="shortcut icon" type="image/png" href="/h5ai/images/h5ai-16x16.png"> <link rel="shortcut icon" type="image/png" href="/h5ai/images/h5ai-16x16.png">
<link rel="apple-touch-icon" type="image/png" href="/h5ai/images/h5ai-48x48.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="http://fonts.googleapis.com/css?family=Ubuntu:regular,italic,bold">
<link rel="stylesheet" type="text/css" href="/h5ai/css/main-js.css"> <link rel="stylesheet" type="text/css" href="/h5ai/css/main-js.css">
<script src="/h5ai/js/lib/modernizr.min.js"></script> <script src="/h5ai/js/lib/modernizr.min.js"></script>
</head> </head>
<body> <body>
<nav class="clearfix"> <div id="selection-rect"></div>
<ul> <nav class="clearfix">
<li id="viewicons" class="view hideOnNoJs"> <ul>
<a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" /><span class="l10n-icons">icons</span></a> <li id="viewicons" class="view hideOnNoJs">
</li> <a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" /><span class="l10n-icons">icons</span></a>
<li id="viewdetails" class="view hideOnNoJs" > </li>
<a href="#"><img src="/h5ai/images/view-details.png" alt="view-details" /><span class="l10n-details">details</span></a> <li id="viewdetails" class="view hideOnNoJs" >
</li> <a href="#"><img src="/h5ai/images/view-details.png" alt="view-details" /><span class="l10n-details">details</span></a>
</ul> </li>
</nav> <li id="download" class="hideOnNoJs">
<section id="content"> <a href="#"><img src="/h5ai/images/download.png" alt="download" /><span class="l10n-download">download</span></a>
<header></header> </li>
<section id="table" class="hideOnJs"> </ul>
<!-- </nav>
The following code was generated by apache's autoindex module. It is not valid HTML 5 for the <section id="content">
reason, that 'align' and 'valign' attributes on the td element are obsolete. Both of them are <header></header>
removed via javascript. The actual page should render as perfect HTML 5, even if the produced <section id="table" class="hideOnJs">
source is not valid HTML 5. <!--
--> 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
removed via javascript. The actual page should render as perfect HTML 5, even if the produced
source is not valid HTML 5.
-->

View File

@@ -2,58 +2,62 @@
<html class="no-js"> <html class="no-js">
<?php include "php/main.php"; ?> <?php include "php/main.php"; ?>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title><?php echo $h5ai->getTitle(); ?></title> <title><?php echo $h5ai->getTitle(); ?></title>
<meta name="h5ai-version" content="h5ai %BUILD_VERSION% (php)"> <meta name="h5ai-version" content="h5ai %BUILD_VERSION% (php)">
<meta name="description" content="Directory index styled with h5ai (http://larsjung.de/h5ai)"> <meta name="description" content="Directory index styled with h5ai (http://larsjung.de/h5ai)">
<meta name="keywords" content="directory, index, autoindex, h5ai"> <meta name="keywords" content="directory, index, autoindex, h5ai">
<link rel="shortcut icon" type="image/png" href="/h5ai/images/h5ai-16x16.png"> <link rel="shortcut icon" type="image/png" href="/h5ai/images/h5ai-16x16.png">
<link rel="apple-touch-icon" type="image/png" href="/h5ai/images/h5ai-48x48.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="http://fonts.googleapis.com/css?family=Ubuntu:regular,italic,bold">
<link rel="stylesheet" type="text/css" href="/h5ai/css/main-php.css"> <link rel="stylesheet" type="text/css" href="/h5ai/css/main-php.css">
<script src="/h5ai/js/lib/modernizr.min.js"></script> <script src="/h5ai/js/lib/modernizr.min.js"></script>
</head> </head>
<body> <body>
<nav class="clearfix"> <div id="selection-rect"></div>
<ul> <nav class="clearfix">
<?php echo $crumb->toHtml(); ?> <ul>
<li id="viewicons" class="view hideOnNoJs"> <?php echo $crumb->toHtml(); ?>
<a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" /><span class="l10n-icons">icons</span></a> <li id="viewicons" class="view hideOnNoJs">
</li> <a href="#"><img src="/h5ai/images/view-icons.png" alt="view-icons" /><span class="l10n-icons">icons</span></a>
<li id="viewdetails" class="view hideOnNoJs" > </li>
<a href="#"><img src="/h5ai/images/view-details.png" alt="view-details" /><span class="l10n-details">details</span></a> <li id="viewdetails" class="view hideOnNoJs" >
</li> <a href="#"><img src="/h5ai/images/view-details.png" alt="view-details" /><span class="l10n-details">details</span></a>
</ul> </li>
</nav> <li id="download" class="hideOnNoJs">
<?php echo $tree->toHtml(); ?> <a href="#"><img src="/h5ai/images/download.png" alt="download" /><span class="l10n-download">download</span></a>
<section id="content"> </li>
<?php echo $customize->getHeader(); ?> </ul>
<?php echo $extended->toHtml(); ?> </nav>
<?php echo $customize->getFooter(); ?> <?php echo $tree->toHtml(); ?>
</section> <section id="content">
<footer class="clearfix"> <?php echo $customize->getHeader(); ?>
<span class="left"> <?php echo $extended->toHtml(); ?>
<a href="http://larsjung.de/h5ai" target="_blank" title="h5ai project page">h5ai %BUILD_VERSION% (php)</a> <?php echo $customize->getFooter(); ?>
</span> </section>
<span class="right"> <footer class="clearfix">
<span class="hideOnJs">JavaScript is disabled!</span> <span class="left">
<span id="langSelector"> <a href="http://larsjung.de/h5ai" target="_blank" title="h5ai project page">h5ai %BUILD_VERSION% (php)</a>
<span class="lang">en</span> - <span class="l10n-lang">english</span> </span>
<span class="langOptions"></span> <span class="right">
</span> <span class="hideOnJs">JavaScript is disabled!</span>
</span> <span id="langSelector">
<span class="center"> <span class="lang">en</span> - <span class="l10n-lang">english</span>
<span class="status default"> <span class="langOptions"></span>
<?php echo $extended->getFolderCount(); ?> <span class="l10n-folders">folders</span> </span>
· </span>
<?php echo $extended->getFileCount(); ?> <span class="l10n-files">files</span> <span class="center">
</span> <span class="status default">
<span class="status dynamic"> <?php echo $extended->getFolderCount(); ?> <span class="l10n-folders">folders</span>
</span> <span class='sep'>·</span>
</span> <?php echo $extended->getFileCount(); ?> <span class="l10n-files">files</span>
</footer> </span>
<script src="/h5ai/js/lib/jquery.min.js"></script> <span class="status dynamic">
<script src="/h5ai/options.js"></script> </span>
<script src="/h5ai/js/main-php.js"></script> </span>
<section id="table"> </footer>
<!-- the following code was generated by apache's autoindex module and gets ignored --> <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 -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

View File

@@ -1,153 +1,119 @@
var Extended = function ( pathCache, h5ai ) { var Extended = function (pathCache, h5ai) {
"use strict";
/*global $*/
var settings = {
customHeader: "h5ai.header.html",
customFooter: "h5ai.footer.html"
},
initTitle = function () {
/******************************* document.title = document.domain + document.location.pathname;
* config try {
*******************************/ document.title = decodeURI(document.title);
} catch (err) {}
},
initBreadcrumb = function () {
this.config = { var idx, part,
customHeader: "h5ai.header.html", $ul = $("body > nav ul"),
customFooter: "h5ai.footer.html" pathname = "/",
}; path = pathCache.getPath(pathname),
pathnameParts = document.location.pathname.split("/");
$ul.append(path.updateCrumbHtml());
/******************************* for (idx in pathnameParts) {
* init part = pathnameParts[idx];
*******************************/ if (part !== "") {
pathname += part + "/";
$ul.append(pathCache.getPath(pathname).updateCrumbHtml());
}
}
},
initExtendedView = function () {
this.init = function () { var $ths = $("#table th"),
$label = $ths.eq(1).find("a"),
$date = $ths.eq(2).find("a"),
$size = $ths.eq(3).find("a"),
sortquery = document.location.search,
order = {
column: (sortquery.indexOf("C=N") >= 0) ? "name" : (sortquery.indexOf("C=M") >= 0) ? "date" : (sortquery.indexOf("C=S") >= 0) ? "size" : h5ai.settings.sortorder.column,
ascending: (sortquery.indexOf("O=A") >= 0) ? true : (sortquery.indexOf("O=D") >= 0) ? false : h5ai.settings.sortorder.ascending
},
$icon, $ul, $li;
try { $ul = $("<ul/>");
document.title = decodeURI( document.domain + document.location.pathname ); $li = $("<li class='header' />")
} catch ( err ) { .appendTo($ul)
document.title = document.domain + document.location.pathname; .append($("<a class='icon'></a>"))
}; .append($("<a class='label' href='" + $label.attr("href") + "'><span class='l10n-name'>" + $label.text() + "</span></a>"))
.append($("<a class='date' href='" + $date.attr("href") + "'><span class='l10n-lastModified'>" + $date.text() + "</span></a>"))
.append($("<a class='size' href='" + $size.attr("href") + "'><span class='l10n-size'>" + $size.text() + "</span></a>"));
this.initBreadcrumb(); // header sort icons
this.initExtendedView(); if (order.ascending) {
this.customize(); $icon = $("<img src='/h5ai/images/ascending.png' class='sort' alt='ascending' />");
this.initCounts(); } else {
}; $icon = $("<img src='/h5ai/images/descending.png' class='sort' alt='descending' />");
}
if (order.column === "date") {
$li.find("a.date").prepend($icon);
} else if (order.column === "size") {
$li.find("a.size").prepend($icon);
} else {
$li.find("a.label").append($icon);
}
// entries
$("#table td").closest("tr").each(function () {
var path = pathCache.getPath(document.location.pathname, this);
$ul.append(path.updateExtendedHtml());
});
$("#extended").append($ul);
/******************************* // empty
* breadcrumb if ($ul.children(".entry:not(.parentfolder)").size() === 0) {
*******************************/ $("#extended").append($("<div class='empty l10n-empty'>empty</div>"));
}
},
customize = function () {
this.initBreadcrumb = function () { $.ajax({
url: settings.customHeader,
dataType: "html",
success: function (data) {
$("#content > header").append($(data)).show();
}
});
var $ul = $( "body > nav ul" ); $.ajax({
url: settings.customFooter,
dataType: "html",
success: function (data) {
$("#content > footer").prepend($(data)).show();
}
});
},
initCounts = function () {
var pathname = "/"; $(".folderCount").text($("#extended .entry.folder:not(.parentfolder)").size());
var path = pathCache.getPathForFolder( pathname ); $(".fileCount").text($("#extended .entry.file").size());
$ul.append( path.updateCrumbHtml() ); },
init = function () {
var pathnameParts = document.location.pathname.split( "/" ); initTitle();
for ( idx in pathnameParts ) { initBreadcrumb();
var part = pathnameParts[idx]; initExtendedView();
if ( part !== "" ) { customize();
pathname += part + "/"; initCounts();
var path = pathCache.getPathForFolder( pathname ); },
$ul.append( path.updateCrumbHtml() ); extended = {
}; init: init
}; };
};
return extended;
/*******************************
* 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 sortquery = document.location.search;
var order = {
column: ( sortquery.indexOf( "C=N" ) >= 0 ) ? "name" : ( sortquery.indexOf( "C=M" ) >= 0 ) ? "date" : ( sortquery.indexOf( "C=S" ) >= 0 ) ? "size" : h5ai.config.sortorder.column,
ascending: ( sortquery.indexOf( "O=A" ) >= 0 ) ? true : ( sortquery.indexOf( "O=D" ) >= 0 ) ? false : h5ai.config.sortorder.ascending
};
var $icon;
if ( order.ascending ) {
$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.column === "date" ) {
$li.find( "a.date" ).prepend( $icon );
} else if ( order.column === "size" ) {
$li.find( "a.size" ).prepend( $icon );
} else {
$li.find( "a.label" ).append( $icon );
};
// entries
$( "#table td" ).closest( "tr" ).each( function () {
var path = pathCache.getPathForTableRow( document.location.pathname, this );
$ul.append( path.updateExtendedHtml() );
} );
$( "#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() );
};
}; };

View File

@@ -1,379 +1,391 @@
var H5ai = function ( options, langs ) { var H5ai = function (options, langs) {
"use strict";
/*global $, window, localStorage*/
/*******************************
* config var defaults = {
*******************************/ store: {
viewmode: "h5ai.viewmode",
var defaults = { lang: "h5ai.lang"
store: { },
viewmode: "h5ai.viewmode", callbacks: {
lang: "h5ai.lang" pathClick: []
}, },
callbacks: {
pathClick: [] viewmodes: ["details", "icons"],
}, sortorder: {
column: "name",
viewmodes: [ "details", "icons" ], ascending: true
sortorder: { },
column: "name", showTree: true,
ascending: true slideTree: true,
}, folderStatus: {},
showTree: true, lang: null,
slideTree: true, useBrowserLang: true,
folderStatus: { setParentFolderLabels: true,
}, linkHoverStates: true,
lang: null,
useBrowserLang: true, dateFormat: "Y-m-d H:i",
setParentFolderLabels: true, ignore: ["h5ai", "h5ai.header.html", "h5ai.footer.html"],
linkHoverStates: true ignoreRE: ["/^\\./"],
}; showThumbs: true
this.config = $.extend( {}, defaults, options ); },
settings = $.extend({}, defaults, options),
pathClick = function (fn) {
/******************************* if ($.isFunction(fn)) {
* public api settings.callbacks.pathClick.push(fn);
*******************************/ }
},
this.pathClick = function ( fn ) { triggerPathClick = function (path, context) {
if ( $.isFunction( fn ) ) { var i, l, a = settings.callbacks.pathClick;
this.config.callbacks.pathClick.push( fn );
}; for (i = 0, l = a.length; i < l; i++) {
return this; a[i].call(window, path, context);
}; }
},
getViewmode = function () {
/******************************* var viewmode = localStorage.getItem(settings.store.viewmode);
* init
*******************************/ return $.inArray(viewmode, settings.viewmodes) >= 0 ? viewmode : settings.viewmodes[0];
},
this.init = function () { applyViewmode = function (viewmode) {
this.applyViewmode(); if (viewmode) {
this.initTopSpace(); localStorage.setItem(settings.store.viewmode, viewmode);
this.initViews(); }
this.initTree(); viewmode = getViewmode();
this.linkHoverStates();
this.initLangSelector( langs ); $("#viewdetails,#viewicons").hide().removeClass("current");
this.localize( langs, this.config.lang, this.config.useBrowserLang );
this.initIndicators(); if (settings.viewmodes.length > 1) {
}; if ($.inArray("details", settings.viewmodes) >= 0) {
$("#viewdetails").show();
}
if ($.inArray("icons", settings.viewmodes) >= 0) {
/******************************* $("#viewicons").show();
* callback triggers }
*******************************/ }
this.triggerPathClick = function ( path, context ) { if (viewmode === "details") {
$("#viewdetails").closest("li").addClass("current");
for ( idx in this.config.callbacks.pathClick ) { $("#extended").addClass("details-view").removeClass("icons-view").show();
this.config.callbacks.pathClick[idx].call( window, path, context ); } else if (viewmode === "icons") {
}; $("#viewicons").closest("li").addClass("current");
}; $("#extended").removeClass("details-view").addClass("icons-view").show();
} else {
$("#extended").hide();
}
/******************************* },
* local stored viewmode initTopSpace = function () {
*******************************/
var adjustTopSpace = function () {
this.getViewmode = function () {
var winHeight = $(window).height(),
var viewmode = localStorage.getItem( this.config.store.viewmode ); navHeight = $("body > nav").outerHeight(),
return $.inArray( viewmode, this.config.viewmodes ) >= 0 ? viewmode : this.config.viewmodes[0]; footerHeight = $("body > footer").outerHeight(),
}; contentSpacing = 50,
treeSpacing = 50;
this.applyViewmode = function ( viewmode ) { $("body").css({
"margin-top": navHeight + contentSpacing,
if ( viewmode !== undefined ) { "margin-bottom": footerHeight + contentSpacing
localStorage.setItem( this.config.store.viewmode, viewmode ); });
};
viewmode = this.getViewmode(); $("#tree").css({
top: navHeight + treeSpacing,
$( "#viewdetails,#viewicons" ).hide().removeClass( "current" ); height: winHeight - navHeight - footerHeight - 36 - 2 * treeSpacing
});
if ( this.config.viewmodes.length > 1 ) {
if ( $.inArray( "details", this.config.viewmodes ) >= 0 ) { try {
$( "#viewdetails" ).show(); $("#tree").get(0).updateScrollbar();
}; } catch (err) {}
if ( $.inArray( "icons", this.config.viewmodes ) >= 0 ) { };
$( "#viewicons" ).show();
}; $(window).resize(function () {
}; adjustTopSpace();
});
if ( viewmode === "details" ) { adjustTopSpace();
$( "#viewdetails" ).closest( "li" ).addClass( "current" ); },
$( "#extended" ).addClass( "details-view" ).removeClass( "icons-view" ).show(); initViews = function () {
} else if ( viewmode === "icons" ) {
$( "#viewicons" ).closest( "li" ).addClass( "current" ); $("#table").remove();
$( "#extended" ).removeClass( "details-view" ).addClass( "icons-view" ).show();
} else { $("#viewdetails").closest("li")
$( "#extended" ).hide(); .click(function () { applyViewmode("details"); });
}; $("#viewicons").closest("li")
}; .click(function () { applyViewmode("icons"); });
// status update
$("#extended .entry a").hover(
/******************************* function () {
* top space, depending on nav height if ($("#extended").hasClass("icons-view")) {
*******************************/ var $this = $(this);
$(".status.default").hide();
this.initTopSpace = function () { $(".status.dynamic")
.empty()
function adjustTopSpace() { .append($this.find(".label").clone())
.append($("<span class='sep'>·</span>"))
var winHeight = $( window ).height(); .append($this.find(".date").clone())
var navHeight = $( "body > nav" ).outerHeight(); .show();
var footerHeight = $( "body > footer" ).outerHeight();
var contentSpacing = 50; if (!$this.closest(".entry").hasClass("folder")) {
var treeSpacing = 50; $(".status.dynamic")
.append($("<span class='sep'>·</span>"))
$( "body" ) .append($this.find(".size").clone());
.css( "margin-top", "" + ( navHeight + contentSpacing ) + "px" ) }
.css( "margin-bottom", "" + ( footerHeight + contentSpacing ) + "px" ); }
},
$( "#tree" ) function () {
.css( "top", "" + ( navHeight + treeSpacing ) + "px" ) $(".status.default").show();
.css( "height", "" + ( winHeight - navHeight - footerHeight - 36 - 2 * treeSpacing ) + "px" ); $(".status.dynamic").empty().hide();
try { }
$( "#tree" ).get( 0 ).updateScrollbar(); );
} catch ( err ) {}; },
}; shiftTree = function (forceVisible, dontAnimate) {
$( window ).resize( function () { var $tree = $("#tree"),
adjustTopSpace(); $extended = $("#extended");
} );
adjustTopSpace(); if (settings.slideTree && $tree.outerWidth() < $extended.offset().left || forceVisible) {
}; if (dontAnimate) {
$tree.stop().css({ left: 0 });
} else {
$tree.stop().animate({ left: 0 });
/******************************* }
* init views } else {
*******************************/ if (dontAnimate) {
$tree.stop().css({ left: 18 - $tree.outerWidth() });
this.initViews = function () { } else {
$tree.stop().animate({ left: 18 - $tree.outerWidth() });
$( "#table" ).remove(); }
}
$( "#viewdetails" ).closest( "li" ) },
.click( $.proxy( function () { initTree = function () {
this.applyViewmode( "details" );
}, this ) ); $("#tree").hover(
$( "#viewicons" ).closest( "li" ) function () { shiftTree(true); },
.click( $.proxy( function () { function () { shiftTree(); }
this.applyViewmode( "icons" ); );
}, this ) ); $(window).resize(function () { shiftTree(); });
shiftTree(false, true);
$( "#extended .entry" ).hover( },
function () { linkHoverStates = function () {
if ( $( "#extended" ).hasClass( "icons-view" ) ) {
$this = $( this ); if (settings.linkHoverStates) {
$( ".status.default" ).hide(); $("a[href^='/']:not(.linkedHoverStates)").each(function () {
$( ".status.dynamic" )
.empty() var $a = $(this).addClass("linkedHoverStates"),
.append( $this.find( ".label" ).clone() ) href = $a.attr("href");
.append( " · " )
.append( $this.find( ".date" ).clone() ) $a.hover(
.show(); function () { $("a[href='" + href + "']").addClass("hover"); },
function () { $("a[href='" + href + "']").removeClass("hover"); }
if ( ! $this.hasClass( "folder" ) ) { );
$( ".status.dynamic" ) });
.append( " · " ) }
.append( $this.find( ".size" ).clone() ); },
} localize = function (langs, lang, useBrowserLang) {
};
}, var storedLang = localStorage.getItem(settings.store.lang),
function () { browserLang, selected, key;
$( ".status.default" ).show();
$( ".status.dynamic" ) if (langs[storedLang]) {
.empty() lang = storedLang;
.hide(); } else if (useBrowserLang) {
} browserLang = navigator.language;
); if (langs[browserLang]) {
}; lang = browserLang;
} else if (browserLang.length > 2 && langs[browserLang.substr(0, 2)]) {
lang = browserLang.substr(0, 2);
}
/******************************* }
* init tree
*******************************/ if (!langs[lang]) {
lang = "en";
this.shiftTree = function ( forceVisible, dontAnimate ) { }
var $tree = $( "#tree" ); selected = langs[lang];
var $extended = $( "#extended" ); if (selected) {
for (key in selected) {
if ( this.config.slideTree && $tree.outerWidth() < $extended.offset().left || forceVisible === true ) { $(".l10n-" + key).text(selected[key]);
if ( dontAnimate === true ) { }
$tree.stop().css( { left: 0 } ); $(".lang").text(lang);
} else { $(".langOption").removeClass("current");
$tree.stop().animate( { left: 0 } ); $(".langOption." + lang).addClass("current");
}; }
} else { },
if ( dontAnimate === true ) { initLangSelector = function (langs) {
$tree.stop().css( { left: 18 - $tree.outerWidth() } );
} else { var idx, lang,
$tree.stop().animate( { left: 18 - $tree.outerWidth() } ); sortedLangsKeys = [],
}; $ul;
};
}; for (lang in langs) {
sortedLangsKeys.push(lang);
}
this.initTree = function () { sortedLangsKeys.sort();
$( "#tree" ).hover( $ul = $("<ul />");
$.proxy( function () { this.shiftTree( true ); }, this ), for (idx in sortedLangsKeys) {
$.proxy( function () { this.shiftTree(); }, this ) (function (lang) {
); $("<li class='langOption' />")
$( window ).resize( $.proxy( function () { this.shiftTree(); }, this ) ); .addClass(lang)
this.shiftTree( false, true ); .text(lang + " - " + langs[lang].lang)
}; .appendTo($ul)
.click(function () {
localStorage.setItem(settings.store.lang, lang);
localize(langs, lang, false);
/******************************* });
* link hover states })(sortedLangsKeys[idx]);
*******************************/ }
$("#langSelector .langOptions").append($ul);
this.linkHoverStates = function () { $("#langSelector").hover(
function () {
if ( !this.config.linkHoverStates ) { var $ele = $(".langOptions");
return; $ele.css("top", "-" + $ele.outerHeight() + "px").stop(true, true).fadeIn();
}; },
function () {
$( "a[href^='/']:not(.linkedHoverStates)" ).each( function () { $(".langOptions").stop(true, true).fadeOut();
}
var $a = $( this ).addClass( "linkedHoverStates" ); );
var href = $a.attr( "href" ); },
$a.hover( initIndicators = function () {
function () {
$( "a[href='" + href + "']" ).addClass( "hover" ); $("#tree .entry.folder:not(.initiatedIndicator)").each(function () {
},
function () { var $entry = $(this).addClass("initiatedIndicator"),
$( "a[href='" + href + "']" ).removeClass( "hover" ); $indicator = $entry.find("> .indicator");
}
); $indicator.click(function (event) {
} );
}; var $content;
if ($indicator.hasClass("unknown")) {
$.get("/h5ai/php/treecontent.php", { "href": $entry.find("> a").attr("href") }, function (html) {
/******************************* $content = $(html);
* localization $indicator.removeClass("unknown");
*******************************/ if ($content.find("> li").size() === 0) {
$indicator.replaceWith($("<span class='blank' />"));
this.initLangSelector = function ( langs ) { } else {
$indicator.addClass("open");
var sortedLangsKeys = []; $entry.find("> .content").replaceWith($content);
for ( lang in langs ) { $("#tree").get(0).updateScrollbar();
sortedLangsKeys.push( lang ); initIndicators();
}; }
sortedLangsKeys.sort(); });
} else if ($indicator.hasClass("open")) {
var THIS = this; $indicator.removeClass("open");
var $ul = $( "<ul />" ); $("#tree").get(0).updateScrollbar(true);
for ( idx in sortedLangsKeys ) { $entry.find("> .content").slideUp(function () {
( function ( lang ) { $("#tree").get(0).updateScrollbar();
$( "<li class='langOption' />" ) });
.addClass( lang ) } else {
.text( lang + " - " + langs[lang]["lang"] ) $indicator.addClass("open");
.appendTo( $ul ) $("#tree").get(0).updateScrollbar(true);
.click( function () { $entry.find("> .content").slideDown(function () {
localStorage.setItem( THIS.config.store.lang, lang ); $("#tree").get(0).updateScrollbar();
THIS.localize( langs, lang, false ); });
} ); }
} )( sortedLangsKeys[idx] ); });
}; });
$( "#langSelector .langOptions" ) },
.append( $ul ); initSelect = function () {
$( "#langSelector" ).hover(
function () { var x = 0,
var $ele = $( ".langOptions" ); y = 0,
$ele.css( "top", "-" + $ele.outerHeight() + "px" ).stop( true, true ).fadeIn(); $window = $(window),
}, selected = function (hrefs) {
function () {
$( ".langOptions" ).stop( true, true ).fadeOut(); var query, idx;
} for (idx in hrefs) {
); query = query ? query + ":" + hrefs[idx] : hrefs[idx];
}; }
query = "/h5ai/php/zipcontent.php?hrefs=" + query;
this.localize = function ( langs, lang, useBrowserLang ) { $("#download").show().find("a").attr("href", query);
},
if ( useBrowserLang === true ) { selectionUpdate = function (event) {
var browserLang = navigator.language;
if ( langs[ browserLang ] !== undefined ) { var l = Math.min(x, event.pageX),
lang = browserLang; t = Math.min(y, event.pageY),
} else if ( browserLang.length > 2 && langs[ browserLang.substr( 0, 2 ) ] !== undefined ) { w = Math.abs(x - event.pageX),
lang = browserLang.substr( 0, 2 ); h = Math.abs(y - event.pageY),
}; sel;
};
event.preventDefault();
if ( langs[ lang ] === undefined ) { $("#selection-rect").css({left: l, top: t, width: w, height: h});
lang = "en";
}; sel = $("#selection-rect").fracs("rect");
$("#extended a").removeClass("selected").each(function () {
var storedLang = localStorage.getItem( this.config.store.lang );
if ( langs[ storedLang ] !== undefined ) { var $a = $(this),
lang = storedLang; rect = $a.fracs("rect"),
}; inter = sel.intersection(rect);
if (inter && !$a.closest(".entry").hasClass("folder-parent")) {
var selected = langs[ lang ]; $a.addClass("selected");
for ( key in selected ) { }
$( ".l10n-" + key ).text( selected[key] ); });
}; },
$( ".lang" ).text( lang ); selectionEnd = function (event) {
$( ".langOption" ).removeClass( "current" );
$( ".langOption." + lang ).addClass( "current" ); event.preventDefault();
}; $("#selection-rect").hide().css({left: 0, top: 0, width: 0, height: 0});
$window.unbind("mousemove", selectionUpdate);
/******************************* var hrefs = [];
* initiate tree indicators $("#extended a.selected").each(function () {
*******************************/ hrefs.push($(this).attr("href"));
});
this.initIndicators = function () { if (hrefs.length > 0) {
selected(hrefs);
var THIS = this; }
$( "#tree .entry.folder:not(.initiatedIndicator)" ).each( function () { },
selectionStart = function (event) {
var $entry = $( this ).addClass( "initiatedIndicator" );
var $indicator = $entry.find( "> .indicator" ); event.preventDefault();
$indicator.click( function( event ) { x = event.pageX;
if ( $indicator.hasClass( "unknown" ) ) { y = event.pageY;
$.get( "/h5ai/php/treecontent.php", { "href": $entry.find( "> a" ).attr( "href" ) }, function ( html ) { $("#download").hide().find("a").attr("href", "#");
$content = $( html ); $("#extended a").removeClass("selected");
$indicator.removeClass( "unknown" ); $("#selection-rect").show().css({left: x, top: y, width: 0, height: 0});
if ( $content.find( "> li" ).size() === 0 ) {
$indicator.replaceWith( $( "<span class='blank' />" ) ); $window
} else { .bind("mousemove", selectionUpdate)
$indicator.addClass( "open" ); .one("mouseup", selectionEnd);
$entry.find( "> .content" ).replaceWith( $content ); },
$( "#tree" ).get( 0 ).updateScrollbar(); noSelection = function (event) {
THIS.initIndicators();
}; event.stopPropagation();
} ); return false;
} else if ( $indicator.hasClass( "open" ) ) { };
$indicator.removeClass( "open" );
$( "#tree" ).get( 0 ).updateScrollbar( true ); $("body>nav,body>footer,#tree,#extended a").bind("mousedown", noSelection);
$entry.find( "> .content" ).slideUp( function() { $("#extended a").live("mousedown", noSelection);
$( "#tree" ).get( 0 ).updateScrollbar(); $window.bind("mousedown", selectionStart);
} ); },
} else { init = function () {
$indicator.addClass( "open" );
$( "#tree" ).get( 0 ).updateScrollbar( true ); applyViewmode();
$entry.find( "> .content" ).slideDown( function() { initTopSpace();
$( "#tree" ).get( 0 ).updateScrollbar(); initViews();
} ); initTree();
}; linkHoverStates();
} ); initLangSelector(langs);
} ); localize(langs, settings.lang, settings.useBrowserLang);
}; initIndicators();
initSelect();
},
h5ai = {
settings: settings,
shiftTree: shiftTree,
linkHoverStates: linkHoverStates,
pathClick: pathClick,
triggerPathClick: triggerPathClick,
init: init
};
return h5ai;
}; };

View File

@@ -0,0 +1,871 @@
/*
* jQuery.fracs 0.10
* http://larsjung.de/fracs
*
* provided under the terms of the MIT License
*/
/*
* ModPlug 0.4
* http://larsjung.de/modplug
*
* provided under the terms of the MIT License
*/
(function ($) {
"use strict";
/*globals jQuery */
/*jslint confusion: true */
var reference = "_mp_api";
$.ModPlug = $.ModPlug || {
plugin: function (namespace, options) {
if (!namespace || $[namespace] || $.fn[namespace]) {
// $.error("No namespace specified, or a plugin already exists on 'jQuery." + namespace + "'");
return !namespace ? 1 : ($[namespace] ? 2 : 3);
}
var defaults = {
statics: {},
methods: {},
defaultStatic: undefined,
defaultMethod: undefined
},
settings = $.extend({}, defaults, options),
staticPlug = function () {
var args, defaultMethod;
args = Array.prototype.slice.call(arguments);
defaultMethod = settings.defaultStatic instanceof Function ? settings.defaultStatic.apply(this, args) : settings.defaultStatic;
if (staticPlug[defaultMethod] instanceof Function) {
return staticPlug[defaultMethod].apply(this, args);
}
$.error("Static method defaulted to '" + defaultMethod + "' does not exist on 'jQuery." + namespace + "'");
},
methods = {},
methodPlug = function (method) {
var args, defaultMethod;
if (methods[method] instanceof Function) {
args = Array.prototype.slice.call(arguments, 1);
return methods[method].apply(this, args);
}
args = Array.prototype.slice.call(arguments);
defaultMethod = settings.defaultMethod instanceof Function ? settings.defaultMethod.apply(this, args) : settings.defaultMethod;
if (methods[defaultMethod] instanceof Function) {
return methods[defaultMethod].apply(this, args);
}
$.error("Method '" + method + "' defaulted to '" + defaultMethod + "' does not exist on 'jQuery." + namespace + "'");
},
api = {
addStatics: function (newStatics) {
$.extend(staticPlug, newStatics);
staticPlug[reference] = api;
return this;
},
addMethods: function (newMethods) {
$.extend(methods, newMethods);
return this;
}
};
api.addStatics(settings.statics).addMethods(settings.methods);
$[namespace] = staticPlug;
$.fn[namespace] = methodPlug;
return 0;
},
module: function (namespace, options) {
if (!$[namespace] || !$[namespace][reference]) {
// $.error("No ModPlug plugin exists on 'jQuery." + namespace + "'");
return !$[namespace] ? 1 : 2;
}
var defaults = {
statics: {},
methods: {}
},
settings = $.extend({}, defaults, options);
$[namespace][reference].addStatics(settings.statics).addMethods(settings.methods);
return 0;
}
};
}(jQuery));
/*
* jQuery.fracs - Core API
*/
(function ($) {
"use strict";
/*globals jQuery, HTMLElement */
/*jslint browser: true, vars: true */
var FracsData = function (htmlElementOrRect) {
var target = htmlElementOrRect,
callbacks = [],
prevFracs;
this.size = function () {
return callbacks.length;
};
this.bind = function (callback) {
if (callback instanceof Function && $.inArray(callback, callbacks) === -1) {
callbacks.push(callback);
}
};
this.unbind = function (callback) {
if (callback instanceof Function) {
var idx = $.inArray(callback, callbacks);
if (idx >= 0) {
callbacks.splice(idx, 1);
}
} else {
callbacks = [];
}
};
this.check = function () {
var rect = target instanceof HTMLElement ? $.fracs.rect(target) : target,
fracs = $.fracs.fracs(rect, $.fracs.viewport());
if (!prevFracs || !prevFracs.equals(fracs)) {
$.each(callbacks, function (idx, callback) {
callback.call(target, fracs, prevFracs);
});
prevFracs = fracs;
}
};
};
var Rect = function (left, top, width, height) {
var fracsData;
this.left = Math.round(left);
this.top = Math.round(top);
this.width = Math.round(width);
this.height = Math.round(height);
this.right = this.left + this.width;
this.bottom = this.top + this.height;
this.equals = function (that) {
return this.left === that.left && this.top === that.top && this.width === that.width && this.height === that.height;
};
this.area = function () {
return this.width * this.height;
};
this.intersection = function (rect) {
var left = Math.max(this.left, rect.left),
right = Math.min(this.right, rect.right),
top = Math.max(this.top, rect.top),
bottom = Math.min(this.bottom, rect.bottom),
width = right - left,
height = bottom - top;
return (width >= 0 && height >= 0) ? new Rect(left, top, width, height) : undefined;
};
this.envelope = function (rect) {
var left = Math.min(this.left, rect.left),
right = Math.max(this.right, rect.right),
top = Math.min(this.top, rect.top),
bottom = Math.max(this.bottom, rect.bottom),
width = right - left,
height = bottom - top;
return new Rect(left, top, width, height);
};
this.bind = function (callback) {
if (!fracsData) {
fracsData = new FracsData(this);
$(window).bind("scroll resize", fracsData.check);
}
fracsData.bind(callback);
};
this.unbind = function (callback) {
if (fracsData) {
fracsData.unbind(callback);
if (fracsData.size() === 0) {
$(window).unbind("scroll resize", fracsData.check);
fracsData = undefined;
}
}
};
this.check = function () {
if (fracsData) {
fracsData.check();
}
};
this.fracs = function () {
$.fracs.fracs(this);
};
};
var FracsResult = function (rectDocument, rectElement, rectViewport, visible, viewport, possible) {
/*jslint confusion: true */
if (!rectDocument || !rectElement || !rectViewport || !visible || !viewport || !possible) {
this.rects = undefined;
this.visible = 0;
this.viewport = 0;
this.possible = 0;
} else {
this.rects = {
document: rectDocument,
element: rectElement,
viewport: rectViewport
};
this.visible = visible;
this.viewport = viewport;
this.possible = possible;
}
this.equals = function (that) {
return this.fracsEqual(that) && this.rectsEqual(that);
};
this.fracsEqual = function (that) {
return this.visible === that.visible && this.viewport === that.viewport && this.possible === that.possible;
};
this.rectsEqual = function (that) {
if (!this.rects || !that.rects) {
return this.rects === that.rects;
}
return this.rects.document.equals(that.rects.document)
&& this.rects.element.equals(that.rects.element)
&& this.rects.viewport.equals(that.rects.viewport);
};
};
var ScrollState = function () {
var document = $.fracs.document(),
viewport = $.fracs.viewport(),
width = document.width - viewport.width,
height = document.height - viewport.height;
this.width = width <= 0 ? undefined : viewport.left / width;
this.height = height <= 0 ? undefined : viewport.top / height;
this.left = viewport.left;
this.top = viewport.top;
this.right = document.right - viewport.right;
this.bottom = document.bottom - viewport.bottom;
this.equals = function (that) {
return this.width === that.width && this.height === that.height
&& this.left === that.left && this.top === that.top
&& this.right === that.right && this.bottom === that.bottom;
};
};
var ScrollStateTracker = function () {
var prevState,
callbacks = [],
check = function () {
var state = new ScrollState();
if (!prevState || !prevState.equals(state)) {
$.each(callbacks, function (idx, callback) {
callback.call(window, state, prevState);
});
prevState = state;
}
};
$(window).bind("resize scroll load", check);
this.bind = function (callback) {
callbacks.push(callback);
};
};
// @beta
var FracsElement = function (htmlElement, fracs) {
this.element = htmlElement;
this.fracs = fracs;
this.update = function () {
var fracs = $.fracs.fracs(this.element),
changed = !this.fracs || !this.fracs.equals(fracs);
this.fracs = fracs;
return changed;
};
};
// @beta
var FracsGroup = function (htmlElements, property, callback) {
var THIS = this,
targets = [],
prevBest = null;
$.each(htmlElements, function (idx, element) {
if (element instanceof HTMLElement) {
targets.push(new FracsElement(element));
}
});
this.check = function () {
var best,
viewport = $.fracs.viewport();
$.each(targets, function (idx, target) {
target.update();
if (!best || target.fracs[property] > best.fracs[property]) {
best = target;
}
});
if (best && best.fracs[property] === 0) {
best = null;
}
if (prevBest !== best) {
callback.call(THIS, best, prevBest);
prevBest = best;
}
};
};
var $document = $(document),
$window = $(window),
$htmlBody = $("html,body"),
scrollStateTracker,
dataNs = "fracs",
statics = {
document: function () {
/*jslint confusion: true */
return new Rect(0, 0, $document.width(), $document.height());
},
viewport: function () {
/*jslint confusion: true */
return new Rect($window.scrollLeft(), $window.scrollTop(), $window.width(), $window.height());
},
rect: function (htmlElement) {
var $target = $(htmlElement),
offset = $target.offset();
if (!$target.is(":visible")) {
return new Rect(0, 0, 0, 0);
}
return new Rect(offset.left, offset.top, $target.outerWidth(), $target.outerHeight());
},
fracs: function (rect, viewport) {
var intersection, intersectionElementSpace, intersectionViewportSpace, intersectionArea, possibleArea;
rect = rect instanceof HTMLElement ? statics.rect(rect) : rect;
viewport = viewport || statics.viewport();
intersection = rect.intersection(viewport);
if (!intersection) {
return new FracsResult();
}
intersectionElementSpace = new Rect(intersection.left - rect.left, intersection.top - rect.top, intersection.width, intersection.height);
intersectionViewportSpace = new Rect(intersection.left - viewport.left, intersection.top - viewport.top, intersection.width, intersection.height);
intersectionArea = intersection.area();
possibleArea = Math.min(rect.width, viewport.width) * Math.min(rect.height, viewport.height);
return new FracsResult(
intersection,
intersectionElementSpace,
intersectionViewportSpace,
intersectionArea / rect.area(),
intersectionArea / viewport.area(),
intersectionArea / possibleArea
);
},
round: function (value, decs) {
if (isNaN(decs) || decs <= 0) {
return Math.round(value);
}
return Math.round(value * Math.pow(10, decs)) / Math.pow(10, decs);
},
scrollTo: function (left, top, duration) {
duration = isNaN(duration) ? 1000 : duration;
$htmlBody.stop(true).animate({ scrollLeft: left, scrollTop: top }, duration);
},
scroll: function (left, top, duration) {
duration = isNaN(duration) ? 1000 : duration;
$htmlBody.stop(true).animate({ scrollLeft: $window.scrollLeft() + left, scrollTop: $window.scrollTop() + top }, duration);
},
scrollState: function (callback) {
if (callback instanceof Function) {
scrollStateTracker = scrollStateTracker || new ScrollStateTracker();
scrollStateTracker.bind(callback);
} else {
return new ScrollState();
}
}
},
methods = {
bind: function (callback) {
return this.each(function () {
var $this = $(this),
data = $this.data(dataNs);
if (!data) {
data = new FracsData(this);
$this.data(dataNs, data);
$window.bind("scroll resize", data.check);
}
data.bind(callback);
});
},
unbind: function (callback) {
return this.each(function () {
var $this = $(this),
data = $this.data(dataNs);
if (data) {
data.unbind(callback);
if (data.size() === 0) {
$this.removeData(dataNs);
$window.unbind("scroll resize", data.check);
}
}
});
},
check: function () {
return this.each(function () {
var data = $(this).data(dataNs);
if (data) {
data.check();
}
});
},
fracs: function () {
return statics.fracs(statics.rect(this.get(0)), statics.viewport());
},
rect: function () {
return statics.rect(this.get(0));
},
max: function (property, callback) {
if (callback instanceof Function) {
var data = new FracsGroup(this, property, callback);
$window.bind("scroll resize", data.check);
data.check();
return this;
} else {
var obj, elements, maxValue;
if ($.inArray(property, [ "possible", "visible", "viewport" ]) >= 0) {
obj = "fracs";
} else if ($.inArray(property, [ "width", "height", "left", "right", "top", "bottom" ]) >= 0) {
obj = "rect";
} else {
return this;
}
this.each(function () {
var fracs = statics[obj](this);
if (!maxValue || fracs[property] > maxValue) {
elements = [ this ];
maxValue = fracs[property];
} else if (fracs[property] === maxValue) {
elements.push(this);
}
});
return $(elements);
}
},
min: function (property) {
var obj, elements, minValue;
if ($.inArray(property, [ "possible", "visible", "viewport" ]) >= 0) {
obj = "fracs";
} else if ($.inArray(property, [ "width", "height", "left", "right", "top", "bottom" ]) >= 0) {
obj = "rect";
} else {
return this;
}
this.each(function () {
var fracs = statics[obj](this);
if (!minValue || fracs[property] < minValue) {
elements = [ this ];
minValue = fracs[property];
} else if (fracs[property] === minValue) {
elements.push(this);
}
});
return $(elements);
},
envelope: function () {
var envelope, rect;
this.each(function () {
rect = statics.rect(this);
envelope = !envelope ? rect : envelope.envelope(rect);
});
return envelope;
},
scrollTo: function (paddingLeft, paddingTop, duration) {
var rect;
paddingLeft = paddingLeft || 0;
paddingTop = paddingTop || 0;
rect = statics.rect(this.get(0));
statics.scrollTo(rect.left - paddingLeft, rect.top - paddingTop, duration);
return this;
},
softLink: function (paddingLeft, paddingTop, duration) {
return this.filter("a[href^=#]").each(function () {
var $a = $(this),
href = $a.attr("href");
$a.click(function () {
$(href).fracs("scrollTo", paddingLeft, paddingTop, duration);
});
});
}
},
defaultStatic = function () {
return "fracs";
},
defaultMethod = function () {
if (arguments.length === 0) {
return "fracs";
} else if (arguments[0] instanceof Function) {
return "bind";
}
};
$.ModPlug.plugin("fracs", {
statics: statics,
methods: methods,
defaultStatic: defaultStatic,
defaultMethod: defaultMethod
});
}(jQuery));
/*
* jQuery.fracs - Outline API
*/
(function ($) {
"use strict";
/*globals jQuery */
/*jslint browser: true, vars: true */
var Outline = function (canvas, options) {
if (!(canvas instanceof HTMLElement && canvas.nodeName.toLowerCase() === "canvas")) {
return undefined;
}
var defaults = {
crop: false,
duration: 0,
focusWidth: 0.5,
focusHeight: 0.5,
autoFocus: true,
styles: [ {
selector: "header,footer,section,article",
fillStyle: "rgb(230,230,230)"
}, {
selector: "h1",
fillStyle: "rgb(240,140,060)"
}, {
selector: "h2",
fillStyle: "rgb(200,100,100)"
}, {
selector: "h3",
fillStyle: "rgb(100,200,100)"
}, {
selector: "h4",
fillStyle: "rgb(100,100,200)"
} ],
viewportStyle: {
fillStyle: "rgba(228,77,38,0.3)"
},
viewportDragStyle: {
fillStyle: "rgba(228,77,38,0.6)"
},
invertViewport: false
},
settings = $.extend({}, defaults, options),
$window = $(window),
$htmlBody = $("html,body"),
$canvas = $(canvas),
width = $canvas.attr("width"),
height = $canvas.attr("height"),
context = canvas.getContext("2d"),
docRect,
vpRect,
scale,
drag = false,
focusWidth,
focusHeight,
scroll = function (event) {
var r, x, y;
r = $canvas.fracs("rect");
x = event.pageX - r.left;
y = event.pageY - r.top;
$.fracs.scrollTo(x / scale - vpRect.width * focusWidth, y / scale - vpRect.height * focusHeight, settings.duration);
},
drawRect = function (context, rect, strokeWidth, strokeStyle, fillStyle, invert) {
if (strokeWidth !== undefined && scale) {
strokeWidth = strokeWidth > 0.2 / scale ? strokeWidth : 0.2 / scale;
}
if (strokeStyle || fillStyle) {
if (invert !== true) {
context.beginPath();
context.rect(rect.left, rect.top, rect.width, rect.height);
if (fillStyle) {
context.fillStyle = fillStyle;
context.fill();
}
if (strokeStyle) {
context.lineWidth = strokeWidth;
context.strokeStyle = strokeStyle;
context.stroke();
}
} else {
if (fillStyle) {
context.beginPath();
context.rect(0, 0, docRect.width, rect.top);
context.rect(0, rect.top, rect.left, rect.height);
context.rect(rect.right, rect.top, docRect.right - rect.right, rect.height);
context.rect(0, rect.bottom, docRect.width, docRect.bottom - rect.bottom);
context.fillStyle = fillStyle;
context.fill();
}
if (strokeStyle) {
context.beginPath();
context.rect(rect.left, rect.top, rect.width, rect.height);
context.lineWidth = strokeWidth;
context.strokeStyle = strokeStyle;
context.stroke();
}
}
}
},
drawElement = function (context, htmlElement, strokeWidth, strokeStyle, fillStyle) {
var $element = $(htmlElement),
rect = $element.fracs("rect");
if ($element.css("visibility") === "hidden") {
return;
}
strokeWidth = strokeWidth === "auto" ? $element.css("border-top-width") : strokeWidth;
strokeStyle = strokeStyle === "auto" ? $element.css("border-top-color") : strokeStyle;
fillStyle = fillStyle === "auto" ? $element.css("background-color") : fillStyle;
drawRect(context, rect, strokeWidth, strokeStyle, fillStyle);
},
drawViewport = function () {
var strokeWidth, strokeStyle, fillStyle;
if (drag && settings.viewportDragStyle) {
strokeWidth = settings.viewportDragStyle.storkeWidth;
strokeStyle = settings.viewportDragStyle.strokeStyle;
fillStyle = settings.viewportDragStyle.fillStyle;
} else {
strokeWidth = settings.viewportStyle.storkeWidth;
strokeStyle = settings.viewportStyle.strokeStyle;
fillStyle = settings.viewportStyle.fillStyle;
}
drawRect(context, vpRect, strokeWidth, strokeStyle, fillStyle, settings.invertViewport);
},
applyStyles = function (context) {
$.each(settings.styles, function (idx, style) {
$(style.selector).each(function () {
drawElement(context, this, style.strokeWidth, style.strokeStyle, style.fillStyle);
});
});
},
draw = function () {
/*jslint confusion: true */
var scaleX, scaleY;
docRect = $.fracs.document();
vpRect = $.fracs.viewport();
scaleX = width / docRect.width;
scaleY = height / docRect.height;
scale = scaleX < scaleY ? scaleX : scaleY;
if (settings.crop) {
$canvas.attr("width", docRect.width * scale).attr("height", docRect.height * scale);
}
context.clearRect(0, 0, $canvas.width(), $canvas.height());
context.scale(scale, scale);
applyStyles(context);
drawViewport();
context.scale(1 / scale, 1 / scale);
},
init = function () {
$canvas
.css("cursor", "pointer")
.mousedown(function (event) {
var r;
event.preventDefault();
drag = true;
if (settings.autoFocus) {
r = $canvas.fracs("rect");
focusWidth = (((event.pageX - r.left) / scale) - vpRect.left) / vpRect.width;
focusHeight = (((event.pageY - r.top) / scale) - vpRect.top) / vpRect.height;
}
if (!settings.autoFocus || focusWidth < 0 || focusWidth > 1 || focusHeight < 0 || focusHeight > 1) {
focusWidth = settings.focusWidth;
focusHeight = settings.focusHeight;
}
scroll(event);
$canvas.css("cursor", "crosshair").addClass("dragOn");
$htmlBody.css("cursor", "crosshair");
$window
.bind("mousemove", scroll)
.one("mouseup", function (event) {
event.preventDefault();
$canvas.css("cursor", "pointer").removeClass("dragOn");
$htmlBody.css("cursor", "auto");
$window.unbind("mousemove", scroll);
drag = false;
draw();
});
});
canvas.onselectstart = function () {
return false;
};
$window.bind("load resize scroll", draw);
draw();
};
init();
this.draw = draw;
};
var dataNs = "outline",
methods = {
outline: function (options) {
return this.each(function () {
var outline;
if (options === "redraw") {
outline = $(this).data(dataNs);
if (outline) {
outline.draw();
}
} else {
outline = new Outline(this, options);
if (outline) {
$(this).data(dataNs, outline);
}
}
});
}
};
$.ModPlug.module("fracs", {
methods: methods
});
}(jQuery));

View File

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

View File

@@ -1,133 +1,147 @@
( function ( $ ) { (function ($) {
var init = function ( htmlElement ) { var init = function (htmlElement) {
var $element = $( htmlElement ); var $element = $(htmlElement),
$scrollbar, $drag, $wrapper, $content, mouseOffsetY, updateId,
update, scroll;
if ( $element.css( "position" ) === undefined || $element.css( "position" ) === "static" ) { if (!$element.css("position") || $element.css("position") === "static") {
$element.css( "position", "relative" ); $element.css("position", "relative");
}; }
var $scrollbar = $( "<div class='scrollbar' />" ); $scrollbar = $("<div class='scrollbar' />");
var $drag = $( "<div class='drag' />" ).appendTo( $scrollbar ); $drag = $("<div class='drag' />").appendTo($scrollbar);
$element $element
.wrapInner( "<div class='wrapper'><div class='content' /></div>" ) .wrapInner("<div class='wrapper'><div class='content' /></div>")
.append( $scrollbar ); .append($scrollbar);
var $wrapper = $element.find( "> .wrapper" ); $wrapper = $element.find("> .wrapper");
var $content = $wrapper.find( "> .content" ); $content = $wrapper.find("> .content");
var mouseOffsetY = 0; mouseOffsetY = 0;
var updateId = undefined;
var update = function ( repeat ) { 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, contentHeight, scrollTop, scrollTopFrac, visVertFrac;
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 ) { if (updateId && !repeat) {
$scrollbar clearInterval(updateId);
.fadeIn( 50 ) updateId = undefined;
.css( { } else if (!updateId && repeat) {
height: $element.innerHeight() + $scrollbar.height() - $scrollbar.outerHeight( true ) updateId = setInterval(function() { update(true); }, 50);
} ); }
$drag
.css( {
top: $scrollbar.height() * scrollTopFrac,
height: $scrollbar.height() * visVertFrac
} );
} else {
$scrollbar.fadeOut( 50 );
};
};
var scroll = function ( event ) {
event.preventDefault();
var clickFrac = ( event.pageY - $scrollbar.offset().top - mouseOffsetY ) / $scrollbar.height();
$wrapper.scrollTop( $content.outerHeight() * clickFrac );
update();
};
$element $wrapper.css("height", $element.height());
.mousewheel( function ( event, delta) { visibleHeight = $element.height();
$wrapper.scrollTop( $wrapper.scrollTop() - 50 * delta ); contentHeight = $content.outerHeight();
update(); scrollTop = $wrapper.scrollTop();
event.stopPropagation(); scrollTopFrac = scrollTop / contentHeight;
event.preventDefault(); visVertFrac = Math.min(visibleHeight / contentHeight, 1);
} )
.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",
cursor: "pointer"
} )
.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.preventDefault();
} )
.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(); 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);
}
};
scroll = function (event) {
var clickFrac = (event.pageY - $scrollbar.offset().top - mouseOffsetY) / $scrollbar.height();
$wrapper.scrollTop($content.outerHeight() * clickFrac);
update();
event.preventDefault();
};
$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",
cursor: "pointer"
})
.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.preventDefault();
})
.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 () { $.fn.scrollpanel = function () {
return this.each( function () { return this.each(function () {
init( this ); init(this);
} ); });
}; };
} )( jQuery ); })(jQuery);

View File

@@ -1,24 +1,29 @@
( function( $ ) { (function ($) {
"use strict";
/*global jQuery, window*/
// http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/ // http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
// modified // modified
$.log = function () { $.log = function () {
$.log.history = $.log.history || []; $.log.history = $.log.history || [];
$.log.history.push( arguments ); $.log.history.push(arguments);
if ( window.console ) { if (window.console) {
window.console.log( Array.prototype.slice.call( arguments ) ); window.console.log(Array.prototype.slice.call(arguments));
}; }
}; };
var Timer = function () { $.timer = (function () {
this.start = new Date().getTime();; var start = $.now(),
this.last = this.start; last = start,
this.log = function ( label ) { timer = {
var now = new Date().getTime(); log: function (label) {
$.log( "timer", label, "+" + (now - this.last), "=" + (now - this.start) ); var now = $.now();
this.last = now; $.log("timer", label, "+" + (now - last), "=" + (now - start));
}; last = now;
}; }
$.timer = new Timer(); };
} )( jQuery ); return timer;
}());
})(jQuery);

View File

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

View File

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

View File

@@ -1,42 +1,30 @@
( function( $ ) { (function($) {
"use strict";
/*global jQuery, h5aiOptions, h5aiLangs*/
// @include "inc/jquery.json.min.js" // @include "inc/jquery.mousewheel.min.js"
// @include "inc/jquery.mousewheel.min.js" // @include "inc/jquery.scrollpanel.js"
// @include "inc/jquery.scrollpanel.js" // @include "inc/jquery.utils.js"
// @include "inc/jquery.utils.js" // @include "inc/jquery.fracs.js"
// @include "inc/path.js" // @include "inc/path.js"
// @include "inc/extended.js" // @include "inc/h5ai.js"
// @include "inc/h5ai.js" // @include "inc/extended.js"
// @include "inc/tree.js" // @include "inc/tree.js"
var pathCache = new PathCache(),
h5ai = new H5ai(h5aiOptions, h5aiLangs),
extended = new Extended(pathCache, h5ai),
tree = new Tree(pathCache, h5ai);
/******************************* $.h5ai = {
* create click: $.proxy(h5ai.pathClick, h5ai)
*******************************/ };
var pathCache = new PathCache(); $(function () {
var h5ai = new H5ai( h5aiOptions, h5aiLangs );
var extended = new Extended( pathCache, h5ai );
var tree = new Tree( pathCache, h5ai );
extended.init();
tree.init();
h5ai.init();
});
/******************************* })(jQuery);
* register public api
*******************************/
$.h5ai = {
click: $.proxy( h5ai.pathClick, h5ai )
};
/*******************************
* init after dom load
*******************************/
$( function() {
extended.init();
tree.init();
h5ai.init();
} );
} )( jQuery );

View File

@@ -1,37 +1,24 @@
( function( $ ) { (function($) {
"use strict";
/*global jQuery, h5aiOptions, h5aiLangs*/
// @include "inc/jquery.json.min.js" // @include "inc/jquery.mousewheel.min.js"
// @include "inc/jquery.mousewheel.min.js" // @include "inc/jquery.scrollpanel.js"
// @include "inc/jquery.scrollpanel.js" // @include "inc/jquery.utils.js"
// @include "inc/jquery.utils.js" // @include "inc/jquery.fracs.js"
// @include "inc/h5ai.js" // @include "inc/h5ai.js"
var h5ai = new H5ai(h5aiOptions, h5aiLangs);
/******************************* $.h5ai = {
* create click: $.proxy(h5ai.pathClick, h5ai)
*******************************/ };
var h5ai = new H5ai( h5aiOptions, h5aiLangs ); $(function () {
h5ai.init();
$("#tree").scrollpanel();
h5ai.shiftTree(false, true);
});
/******************************* })(jQuery);
* register public api
*******************************/
$.h5ai = {
click: $.proxy( h5ai.pathClick, h5ai )
};
/*******************************
* init after dom load
*******************************/
$( function() {
h5ai.init();
$( "#tree" ).scrollpanel();
h5ai.shiftTree( false, true );
} );
} )( jQuery );

View File

@@ -13,7 +13,7 @@ h5aiOptions = {
* The user selected view mode is also stored local in modern browsers * The user selected view mode is also stored local in modern browsers
* so that it will be persistent. * so that it will be persistent.
*/ */
"viewmodes": [ "details", "icons" ], "viewmodes": ["details", "icons"],
/* /*
* Default sort order. Valid values for column are "name", "date" and * Default sort order. Valid values for column are "name", "date" and
@@ -50,12 +50,7 @@ h5aiOptions = {
* as a non auto indexed folder, that means a folder containing an * as a non auto indexed folder, that means a folder containing an
* appropriate default index file. * appropriate default index file.
*/ */
"folderStatus": { "folderStatus": {},
/*
* for example:
* "/some/folder/": 200
*/
},
/* /*
* Localization, for example "en", "de" etc. - see h5aiLangs below for * Localization, for example "en", "de" etc. - see h5aiLangs below for
@@ -95,8 +90,8 @@ h5aiOptions = {
* by the complete filename or by a regular expression. * by the complete filename or by a regular expression.
* http://www.php.net/manual/en/function.preg-match.php * http://www.php.net/manual/en/function.preg-match.php
*/ */
"ignore": [ "h5ai", "h5ai.header.html", "h5ai.footer.html" ], "ignore": ["h5ai", "h5ai.header.html", "h5ai.footer.html"],
"ignoreRE": [ "/^\\./" ], "ignoreRE": ["/^\\./"],
/* /*
* Only used in PHP implementation. * Only used in PHP implementation.

View File

@@ -7,87 +7,87 @@
############################################## ##############################################
class Cache { class Cache {
private $dir; private $dir;
function __construct( $dir ) { function __construct($dir) {
$this->dir = $dir; $this->dir = $dir;
} }
private function _name( $key ) { private function _name($key) {
return $this->dir . "/" . sha1( $key ); return $this->dir . "/" . sha1($key);
} }
public function get( $key, $expiration = 3600 ) { public function get($key, $expiration = 3600) {
if ( !is_dir( $this->dir ) || !is_writable( $this->dir ) ) { if (!is_dir($this->dir) || !is_writable($this->dir)) {
return false; return false;
} }
$cache_path = $this->_name( $key ); $cache_path = $this->_name($key);
if ( !@file_exists( $cache_path ) ) { if (!@file_exists($cache_path)) {
return false; return false;
} }
if ( filemtime( $cache_path ) < ( time() - $expiration ) ) { if (filemtime($cache_path) < (time() - $expiration)) {
$this->clear( $key ); $this->clear($key);
return false; return false;
} }
if ( !$fp = @fopen( $cache_path, "rb" ) ) { if (!$fp = @fopen($cache_path, "rb")) {
return false; return false;
} }
flock( $fp, LOCK_SH ); flock($fp, LOCK_SH);
$cache = ""; $cache = "";
if ( filesize( $cache_path ) > 0 ) { if (filesize($cache_path) > 0) {
$cache = unserialize( fread( $fp, filesize( $cache_path ) ) ); $cache = unserialize(fread($fp, filesize($cache_path)));
} else { } else {
$cache = null; $cache = null;
} }
flock( $fp, LOCK_UN ); flock($fp, LOCK_UN);
fclose( $fp ); fclose($fp);
return $cache; return $cache;
} }
public function set( $key, $data ) { public function set($key, $data) {
if ( !is_dir( $this->dir ) || !is_writable( $this->dir ) ) { if (!is_dir($this->dir) || !is_writable($this->dir)) {
return false; return false;
} }
$cache_path = $this->_name( $key ); $cache_path = $this->_name($key);
if ( ! $fp = fopen( $cache_path, "wb" ) ) { if (! $fp = fopen($cache_path, "wb")) {
return false; return false;
} }
if ( flock( $fp, LOCK_EX ) ) { if (flock($fp, LOCK_EX)) {
fwrite( $fp, serialize( $data ) ); fwrite($fp, serialize($data));
flock( $fp, LOCK_UN ); flock($fp, LOCK_UN);
} else { } else {
return false; return false;
} }
fclose( $fp ); fclose($fp);
@chmod( $cache_path, 0777 ); @chmod($cache_path, 0777);
return true; return true;
} }
public function clear( $key ) { public function clear($key) {
$cache_path = $this->_name( $key ); $cache_path = $this->_name($key);
if ( file_exists( $cache_path ) ) { if (file_exists($cache_path)) {
unlink( $cache_path ); unlink($cache_path);
return true; return true;
} }
return false; return false;
} }
} }
?> ?>

View File

@@ -1,52 +1,52 @@
<?php <?php
class Crumb { class Crumb {
private $h5ai, $parts; private $h5ai, $parts;
public function __construct( $h5ai ) { public function __construct($h5ai) {
$this->h5ai = $h5ai; $this->h5ai = $h5ai;
$this->parts = array(); $this->parts = array();
$href = $h5ai->getAbsHref(); $href = $h5ai->getAbsHref();
while ( $href !== "/" && $href !== "//" ) { while ($href !== "/" && $href !== "//") {
$this->parts[] = $href; $this->parts[] = $href;
$href = dirname( $href ) . "/"; $href = dirname($href) . "/";
} }
$this->parts[] = "/"; $this->parts[] = "/";
$this->parts = array_reverse( $this->parts ); $this->parts = array_reverse($this->parts);
} }
public function toHtml() { public function toHtml() {
$html = ""; $html = "";
$idx = 0; $idx = 0;
foreach( $this->parts as $href ) { foreach($this->parts as $href) {
$idx++; $idx++;
$classes = "crumb folder" . ( $idx === 1 ? " domain" : "" ) . ( $idx === count( $this->parts ) ? " current" : "" ); $classes = "crumb folder" . ($idx === 1 ? " domain" : "") . ($idx === count($this->parts) ? " current" : "");
$image = "/h5ai/images/" . ( $idx === 1 ? "home.png" : "crumb.png" ); $image = "/h5ai/images/" . ($idx === 1 ? "home.png" : "crumb.png");
$label = $this->h5ai->getLabel( $href ); $label = $this->h5ai->getLabel($href);
$hint = ""; $hint = "";
$code = $this->h5ai->getHttpCode( $href ); $code = $this->h5ai->getHttpCode($href);
$classes .= " checkedHttpCode"; $classes .= " checkedHttpCode";
if ( $code !== "h5ai" ) { if ($code !== "h5ai") {
if ( $code === 200 ) { if ($code === 200) {
$hint = "<img class='hint' src='/h5ai/images/page.png' alt='page' />"; $hint = "<img class='hint' src='/h5ai/images/page.png' alt='page' />";
} else { } else {
$hint = "<span class='hint'>(" . $code . ")</span>"; $hint = "<span class='hint'>(" . $code . ")</span>";
} }
} }
$html .= "<li class='$classes'>\n"; $html .= "<li class='$classes'>\n";
$html .= "\t<a href='$href'>\n"; $html .= "\t<a href='$href'>\n";
$html .= "\t\t<img src='$image' alt='>' />" . $label . $hint . "\n"; $html .= "\t\t<img src='$image' alt='>' />" . $label . $hint . "\n";
$html .= "\t</a>\n"; $html .= "\t</a>\n";
$html .= "</li>\n"; $html .= "</li>\n";
} }
return $html; return $html;
} }
} }
?> ?>

View File

@@ -1,27 +1,27 @@
<?php <?php
class Customize { class Customize {
private $h5ai; private $h5ai;
public function __construct( $h5ai ) { public function __construct($h5ai) {
$this->h5ai = $h5ai; $this->h5ai = $h5ai;
} }
public function getHeader() { public function getHeader() {
return $this->getContent( $this->h5ai->getAbsPath() . "/" . "h5ai.header.html", "header" ); return $this->getContent($this->h5ai->getAbsPath() . "/" . "h5ai.header.html", "header");
} }
public function getFooter() { public function getFooter() {
return $this->getContent( $this->h5ai->getAbsPath() . "/" . "h5ai.footer.html", "footer" ); return $this->getContent($this->h5ai->getAbsPath() . "/" . "h5ai.footer.html", "footer");
} }
private function getContent( $file, $tag ) { private function getContent($file, $tag) {
return file_exists( $file ) ? ( "<" . $tag . ">" . file_get_contents( $file ) . "</" . $tag . ">" ) : ""; return file_exists($file) ? ("<" . $tag . ">" . file_get_contents($file) . "</" . $tag . ">") : "";
} }
} }
?> ?>

View File

@@ -4,220 +4,220 @@ require_once "thumbnail.php";
class Entry { class Entry {
private $h5ai, $label, $absPath, $absHref, $date, $isFolder, $type, $size, $thumbTypes; private $h5ai, $label, $absPath, $absHref, $date, $isFolder, $type, $size, $thumbTypes;
public function __construct( $h5ai, $absPath, $absHref, $type = null, $label = null ) { public function __construct($h5ai, $absPath, $absHref, $type = null, $label = null) {
$this->h5ai = $h5ai; $this->h5ai = $h5ai;
$this->label = $label !== null ? $label : $this->h5ai->getLabel( $absHref ); $this->label = $label !== null ? $label : $this->h5ai->getLabel($absHref);
$this->absPath = $this->h5ai->normalizePath( $absPath, false ); $this->absPath = $this->h5ai->normalizePath($absPath, false);
$this->isFolder = is_dir( $this->absPath ); $this->isFolder = is_dir($this->absPath);
$this->absHref = $this->h5ai->normalizePath( $absHref, $this->isFolder ); $this->absHref = $this->h5ai->normalizePath($absHref, $this->isFolder);
$this->date = filemtime( $this->absPath ); $this->date = filemtime($this->absPath);
if ( $this->isFolder ) { if ($this->isFolder) {
$this->type = $type !== null ? $type : "folder"; $this->type = $type !== null ? $type : "folder";
$this->size = ""; $this->size = "";
} else { } else {
$this->type = $type !== null ? $type : $this->h5ai->getType( $this->absPath ); $this->type = $type !== null ? $type : $this->h5ai->getType($this->absPath);
$this->size = filesize( $this->absPath ); $this->size = filesize($this->absPath);
} }
$this->thumbTypes = array( "bmp", "gif", "ico", "image", "jpg", "png", "tiff" ); $this->thumbTypes = array("bmp", "gif", "ico", "image", "jpg", "png", "tiff");
} }
public function isFolder() { public function isFolder() {
return $this->isFolder; return $this->isFolder;
} }
function compare( $that, $sortOrder ) { function compare($that, $sortOrder) {
if ( $this->isFolder && !$that->isFolder ) { if ($this->isFolder && !$that->isFolder) {
return -1; return -1;
} }
if ( !$this->isFolder && $that->isFolder ) { if (!$this->isFolder && $that->isFolder) {
return 1; return 1;
} }
$res = 0; $res = 0;
if ( $sortOrder[ "column" ] === "name" ) { if ($sortOrder[ "column" ] === "name") {
$res = strcasecmp( $this->absPath, $that->absPath ); $res = strcasecmp($this->absPath, $that->absPath);
} else if ( $sortOrder[ "column" ] === "date" ) { } else if ($sortOrder[ "column" ] === "date") {
$res = $this->date - $that->date; $res = $this->date - $that->date;
} else if ( $sortOrder[ "column" ] === "size" ) { } else if ($sortOrder[ "column" ] === "size") {
$res = $this->size - $that->size; $res = $this->size - $that->size;
} }
if ( ! $sortOrder[ "ascending" ] ) { if (! $sortOrder[ "ascending" ]) {
$res = -$res; $res = -$res;
} }
return $res; return $res;
} }
public function toHtml( $dateFormat ) { public function toHtml($dateFormat) {
$classes = "entry " . $this->type; $classes = "entry " . $this->type;
$img = $this->type; $img = $this->type;
$smallImg = "/h5ai/icons/16x16/" . $this->type . ".png"; $smallImg = "/h5ai/icons/16x16/" . $this->type . ".png";
$bigImg = "/h5ai/icons/48x48/" . $this->type . ".png"; $bigImg = "/h5ai/icons/48x48/" . $this->type . ".png";
$hint = ""; $hint = "";
$dateLabel = date( $dateFormat, $this->date ); $dateLabel = date($dateFormat, $this->date);
if ( $this->isFolder && $this->type !== "folder-parent" ) { if ($this->isFolder && $this->type !== "folder-parent") {
$code = $this->h5ai->getHttpCode( $this->absHref ); $code = $this->h5ai->getHttpCode($this->absHref);
$classes .= " checkedHttpCode"; $classes .= " checkedHttpCode";
if ( $code !== "h5ai" ) { if ($code !== "h5ai") {
if ( $code === 200 ) { if ($code === 200) {
$img = "folder-page"; $img = "folder-page";
$smallImg = "/h5ai/icons/16x16/folder-page.png"; $smallImg = "/h5ai/icons/16x16/folder-page.png";
$bigImg = "/h5ai/icons/48x48/folder-page.png"; $bigImg = "/h5ai/icons/48x48/folder-page.png";
} else { } else {
$classes .= " error"; $classes .= " error";
$hint = "<span class='hint'> " . $code . " </span>"; $hint = "<span class='hint'> " . $code . " </span>";
} }
} }
} }
if ( $this->h5ai->showThumbs() && in_array( $this->type, $this->thumbTypes ) ) { if ($this->h5ai->showThumbs() && in_array($this->type, $this->thumbTypes)) {
$classes .= " thumb"; $classes .= " thumb";
$thumbnail = new Thumbnail( $this->absPath, "square", 16, 16 ); $thumbnail = new Thumbnail($this->absPath, "square", 16, 16);
$thumbnail->create(); $thumbnail->create();
$smallImg = file_exists( $thumbnail->getPath() ) ? $thumbnail->getHref() : $thumbnail->getLiveHref(); $smallImg = file_exists($thumbnail->getPath()) ? $thumbnail->getHref() : $thumbnail->getLiveHref();
$thumbnail = new Thumbnail( $this->absPath, "rational", 96, 46 ); $thumbnail = new Thumbnail($this->absPath, "rational", 96, 46);
$thumbnail->create(); $thumbnail->create();
$bigImg = file_exists( $thumbnail->getPath() ) ? $thumbnail->getHref() : $thumbnail->getLiveHref(); $bigImg = file_exists($thumbnail->getPath()) ? $thumbnail->getHref() : $thumbnail->getLiveHref();
} }
$html = "\t<li class='" . $classes . "'>\n"; $html = "\t<li class='" . $classes . "'>\n";
$html .= "\t\t<a href='" . $this->absHref . "'>\n"; $html .= "\t\t<a href='" . $this->absHref . "'>\n";
$html .= "\t\t\t<span class='icon small'><img src='" . $smallImg . "' alt='" . $img . "' /></span>\n"; $html .= "\t\t\t<span class='icon small'><img src='" . $smallImg . "' alt='" . $img . "' /></span>\n";
$html .= "\t\t\t<span class='icon big'><img src='" . $bigImg . "' alt='" . $img . "' /></span>\n"; $html .= "\t\t\t<span class='icon big'><img src='" . $bigImg . "' alt='" . $img . "' /></span>\n";
$html .= "\t\t\t<span class='label'>" . $this->label . $hint . "</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='date'>" . $dateLabel . "</span>\n";
$html .= "\t\t\t<span class='size'>" . $this->formatSize( $this->size ) . "</span>\n"; $html .= "\t\t\t<span class='size'>" . $this->formatSize($this->size) . "</span>\n";
$html .= "\t\t</a>\n"; $html .= "\t\t</a>\n";
$html .= "\t</li>\n"; $html .= "\t</li>\n";
return $html; return $html;
} }
private function formatSize( $size ) { private function formatSize($size) {
$units = array( 'B', 'KB', 'MB', 'GB', 'TB' ); $units = array('B', 'KB', 'MB', 'GB', 'TB');
for ( $i = 0; $size >= 1024 && $i < 4; $i++ ) { for ($i = 0; $size >= 1024 && $i < 4; $i++) {
$size /= 1024; $size /= 1024;
} }
return round( $size, 0 ) . " " . $units[$i]; return round($size, 0) . " " . $units[$i];
} }
} }
class Extended { class Extended {
private $h5ai, $parent, $content; private $h5ai, $parent, $content;
public function __construct( $h5ai ) { public function __construct($h5ai) {
$this->h5ai = $h5ai; $this->h5ai = $h5ai;
$this->parent = null; $this->parent = null;
$this->content = array(); $this->content = array();
$this->loadContent(); $this->loadContent();
} }
private function loadContent() { private function loadContent() {
if ( $this->h5ai->getAbsHref() !== "/" ) { if ($this->h5ai->getAbsHref() !== "/") {
$options = $this->h5ai->getOptions(); $options = $this->h5ai->getOptions();
$parentPath = dirname( $this->h5ai->getAbsPath() ); $parentPath = dirname($this->h5ai->getAbsPath());
$parentHref = dirname( $this->h5ai->getAbsHref() ); $parentHref = dirname($this->h5ai->getAbsHref());
$label = $options["setParentFolderLabels"] === true ? $this->h5ai->getLabel( $parentHref ) : "<span class='l10n-parentDirectory'>Parent Directory</span>"; $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->parent = new Entry($this->h5ai, $parentPath, $parentHref, "folder-parent", $label);
} }
$this->content = array(); $this->content = array();
$files = $this->h5ai->readDir( $this->h5ai->getAbsPath() ); $files = $this->h5ai->readDir($this->h5ai->getAbsPath());
foreach ( $files as $file ) { foreach ($files as $file) {
$absPath = $this->h5ai->getAbsPath() . "/" . $file; $absPath = $this->h5ai->getAbsPath() . "/" . $file;
$absHref = $this->h5ai->getAbsHref() . rawurlencode( $file ); $absHref = $this->h5ai->getAbsHref() . rawurlencode($file);
$this->content[$absPath] = new Entry( $this->h5ai, $absPath, $absHref ); $this->content[$absPath] = new Entry($this->h5ai, $absPath, $absHref);
} }
$this->sort(); $this->sort();
} }
public function cmpEntries( $p1, $p2 ) { public function cmpEntries($p1, $p2) {
return $p1->compare( $p2, $this->h5ai->getSortOrder() ); return $p1->compare($p2, $this->h5ai->getSortOrder());
} }
public function sort() { public function sort() {
uasort( $this->content, array( $this, "cmpEntries" ) ); uasort($this->content, array($this, "cmpEntries"));
} }
public function getFolderCount() { public function getFolderCount() {
$count = 0; $count = 0;
foreach( $this->content as $entry ) { foreach($this->content as $entry) {
if ( $entry->isFolder() ) { if ($entry->isFolder()) {
$count++; $count++;
} }
} }
return $count; return $count;
} }
public function getFileCount() { public function getFileCount() {
$count = 0; $count = 0;
foreach( $this->content as $entry ) { foreach($this->content as $entry) {
if ( !$entry->isFolder() ) { if (!$entry->isFolder()) {
$count++; $count++;
} }
} }
return $count; return $count;
} }
public function toHtml() { public function toHtml() {
$html = "<section id='extended' class='" . $this->h5ai->getView() . "-view clearfix'>\n"; $html = "<section id='extended' class='" . $this->h5ai->getView() . "-view clearfix'>\n";
$html .= "<ul>\n"; $html .= "<ul>\n";
$html .= $this->generateHeaders(); $html .= $this->generateHeaders();
if ( $this->parent !== null ) { if ($this->parent !== null) {
$html .= $this->parent->toHtml( $this->h5ai->getDateFormat() ); $html .= $this->parent->toHtml($this->h5ai->getDateFormat());
} }
foreach( $this->content as $entry ) { foreach($this->content as $entry) {
$html .= $entry->toHtml( $this->h5ai->getDateFormat() ); $html .= $entry->toHtml($this->h5ai->getDateFormat());
} }
$html .= "</ul>\n"; $html .= "</ul>\n";
if ( count( $this->content ) === 0 ) { if (count($this->content) === 0) {
$html .= "<div class='empty l10n-empty'>empty</div>"; $html .= "<div class='empty l10n-empty'>empty</div>";
} }
$html .="</section>"; $html .="</section>";
return $html; return $html;
} }
public function generateHeaders() { public function generateHeaders() {
$asc = "<img src='/h5ai/images/ascending.png' class='sort' alt='ascending' />"; $asc = "<img src='/h5ai/images/ascending.png' class='sort' alt='ascending' />";
$desc = "<img src='/h5ai/images/descending.png' class='sort' alt='descending' />"; $desc = "<img src='/h5ai/images/descending.png' class='sort' alt='descending' />";
$so = $this->h5ai->getSortOrder(); $so = $this->h5ai->getSortOrder();
$order = $so["ascending"] ? $asc : $desc; $order = $so["ascending"] ? $asc : $desc;
$nameHref = "?col=name" . ( $so["column"] === "name" && $so["ascending"] ? "&asc=false" : "&asc=true" ); $nameHref = "?col=name" . ($so["column"] === "name" && $so["ascending"] ? "&asc=false" : "&asc=true");
$dateHref = "?col=date" . ( $so["column"] === "date" && $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" ); $sizeHref = "?col=size" . ($so["column"] === "size" && $so["ascending"] ? "&asc=false" : "&asc=true");
$nameSort = $so["column"] === "name" ? $order : ""; $nameSort = $so["column"] === "name" ? $order : "";
$dateSort = $so["column"] === "date" ? $order : ""; $dateSort = $so["column"] === "date" ? $order : "";
$sizeSort = $so["column"] === "size" ? $order : ""; $sizeSort = $so["column"] === "size" ? $order : "";
$html = "\t<li class='header'>\n"; $html = "\t<li class='header'>\n";
$html .= "\t\t<a class='icon'></a>\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='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='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\t<a class='size' href='$sizeHref'>$sizeSort<span class='l10n-size'>Size</span></a>\n";
$html .= "\t</li>\n"; $html .= "\t</li>\n";
return $html; return $html;
} }
} }
?> ?>

View File

@@ -3,268 +3,268 @@
require_once "cache.php"; require_once "cache.php";
class H5ai { class H5ai {
private static $SORT_ORDER = array( "column" => "name", "ascending" => true ); private static $SORT_ORDER = array("column" => "name", "ascending" => true);
private static $VIEWMODES = array( "details", "icons" ); private static $VIEWMODES = array("details", "icons");
private $docRoot, $domain, $options, $types, $cache, $absHref, $absPath, $ignore, $ignoreRE, $sortOrder, $dateFormat, $view; private $docRoot, $domain, $options, $types, $cache, $absHref, $absPath, $ignore, $ignoreRE, $sortOrder, $dateFormat, $view;
public function __construct() { public function __construct() {
$this->docRoot = getenv( "DOCUMENT_ROOT" ); $this->docRoot = getenv("DOCUMENT_ROOT");
$this->domain = getenv( "HTTP_HOST" ); $this->domain = getenv("HTTP_HOST");
$this->options = $this->loadOptions( $this->docRoot . "/h5ai/options.js" ); $this->options = $this->loadOptions($this->docRoot . "/h5ai/options.js");
$this->types = $this->loadTypes( $this->docRoot . "/h5ai/types.txt" ); $this->types = $this->loadTypes($this->docRoot . "/h5ai/types.txt");
$this->cache = new Cache( $this->docRoot . "/h5ai/cache" ); $this->cache = new Cache($this->docRoot . "/h5ai/cache");
$this->absHref = $this->normalizePath( preg_replace( '/\\?.*/', '', getenv( "REQUEST_URI" ) ), true ); $this->absHref = $this->normalizePath(preg_replace('/\\?.*/', '', getenv("REQUEST_URI")), true);
$this->absPath = $this->normalizePath( $this->docRoot . rawurldecode( $this->absHref ), false ); $this->absPath = $this->normalizePath($this->docRoot . rawurldecode($this->absHref), false);
$this->ignore = $this->options["options"]["ignore"]; $this->ignore = $this->options["options"]["ignore"];
$this->ignoreRE = $this->options["options"]["ignoreRE"]; $this->ignoreRE = $this->options["options"]["ignoreRE"];
$defaultSortOrder = $this->options["options"]["sortorder"]; $defaultSortOrder = $this->options["options"]["sortorder"];
$this->sortOrder = array( $this->sortOrder = array(
"column" => array_key_exists( "col", $_REQUEST ) ? $_REQUEST["col"] : $defaultSortOrder["column"], "column" => array_key_exists("col", $_REQUEST) ? $_REQUEST["col"] : $defaultSortOrder["column"],
"ascending" => array_key_exists( "asc", $_REQUEST ) ? $_REQUEST["asc"] !== "false" : $defaultSortOrder["ascending"] "ascending" => array_key_exists("asc", $_REQUEST) ? $_REQUEST["asc"] !== "false" : $defaultSortOrder["ascending"]
); );
$this->dateFormat = $this->options["options"]["dateFormat"]; $this->dateFormat = $this->options["options"]["dateFormat"];
$this->view = array_key_exists( "view", $_REQUEST ) ? $_REQUEST["view"] : $this->options["options"]["viewmodes"][0]; $this->view = array_key_exists("view", $_REQUEST) ? $_REQUEST["view"] : $this->options["options"]["viewmodes"][0];
if ( !in_array( $this->view, H5ai::$VIEWMODES ) ) { if (!in_array($this->view, H5ai::$VIEWMODES)) {
$this->view = H5ai::$VIEWMODES[0]; $this->view = H5ai::$VIEWMODES[0];
} }
} }
private function loadOptions( $file ) { private function loadOptions($file) {
$str = file_exists( $file ) ? file_get_contents( $file ) : ""; $str = file_exists($file) ? file_get_contents($file) : "";
$str = preg_replace( "/\/\*.*?\*\//s", "", $str ); $str = preg_replace("/\/\*.*?\*\//s", "", $str);
$optstr = preg_replace( "/^.*h5aiOptions\s*=\s*/s", "", $str ); $optstr = preg_replace("/^.*h5aiOptions\s*=\s*/s", "", $str);
$optstr = preg_replace( "/;.*/s", "", $optstr ); $optstr = preg_replace("/;.*/s", "", $optstr);
$options = json_decode( $optstr, true ); $options = json_decode($optstr, true);
$langstr = preg_replace( "/^.*h5aiLangs\s*=\s*/s", "", $str ); $langstr = preg_replace("/^.*h5aiLangs\s*=\s*/s", "", $str);
$langstr = preg_replace( "/;.*/s", "", $langstr ); $langstr = preg_replace("/;.*/s", "", $langstr);
$langs = json_decode( $langstr, true ); $langs = json_decode($langstr, true);
return array( "options" => $options, "langs" => $langs ); return array("options" => $options, "langs" => $langs);
} }
private function loadTypes( $file ) { private function loadTypes($file) {
$lines = file( $file ); $lines = file($file);
$types = array(); $types = array();
foreach( $lines as $line ) { foreach($lines as $line) {
if ( substr( $line, 0, 1 ) === '#' ) { if (substr($line, 0, 1) === '#') {
continue; continue;
} }
$types[] = preg_split( "/\s+/", $line ); $types[] = preg_split("/\s+/", $line);
} }
return $types; return $types;
} }
public function getDocRoot() { public function getDocRoot() {
return $this->docRoot; return $this->docRoot;
} }
public function getDomain() { public function getDomain() {
return $this->domain; return $this->domain;
} }
public function getView() { public function getView() {
return $this->view; return $this->view;
} }
public function getOptions() { public function getOptions() {
return $this->options["options"]; return $this->options["options"];
} }
public function getLangs() { public function getLangs() {
return $this->options["langs"]; return $this->options["langs"];
} }
public function getAbsHref( $absPath = null, $endWithSlash = true ) { public function getAbsHref($absPath = null, $endWithSlash = true) {
if ( $absPath === null ) { if ($absPath === null) {
return $this->absHref; return $this->absHref;
} }
return $this->normalizePath( rawurlencode( preg_replace( "!^" . $this->docRoot . "!", "", $absPath ) ), $endWithSlash ); return $this->normalizePath(rawurlencode(preg_replace("!^" . $this->docRoot . "!", "", $absPath)), $endWithSlash);
} }
public function getAbsPath( $absHref = null ) { public function getAbsPath($absHref = null) {
if ( $absHref === null ) { if ($absHref === null) {
return $this->absPath; return $this->absPath;
} }
return $this->normalizePath( $this->docRoot . rawurldecode( $absHref ), false ); return $this->normalizePath($this->docRoot . rawurldecode($absHref), false);
} }
public function getSortOrder() { public function getSortOrder() {
return $this->sortOrder; return $this->sortOrder;
} }
public function getDateFormat() { public function getDateFormat() {
return $this->dateFormat; return $this->dateFormat;
} }
public function showThumbs() { public function showThumbs() {
return $this->options["options"]["showThumbs"] === true; return $this->options["options"]["showThumbs"] === true;
} }
public function getTitle() { public function getTitle() {
$title = $this->domain . rawurldecode( $this->absHref ); $title = $this->domain . rawurldecode($this->absHref);
$title = preg_replace( "/\/$/", "", $title ); $title = preg_replace("/\/$/", "", $title);
$title = preg_replace( "/\//", " > ", $title ); $title = preg_replace("/\//", " > ", $title);
if ( $this->absHref !== "/" ) { if ($this->absHref !== "/") {
$title = basename( $this->absPath ) . " - " . $title; $title = basename($this->absPath) . " - " . $title;
} }
return $title; return $title;
} }
public function getType( $absPath ) { public function getType($absPath) {
foreach( $this->types as $type ) { foreach($this->types as $type) {
foreach( array_slice( $type, 1 ) as $pattern ) { foreach(array_slice($type, 1) as $pattern) {
if ( $this->endsWith( $absPath, $pattern ) ) { if ($this->endsWith($absPath, $pattern)) {
return $type[0]; return $type[0];
} }
} }
} }
return "unknown"; return "unknown";
} }
public function ignoreThisFile( $file ) { public function ignoreThisFile($file) {
# always ignore # always ignore
if ( $file === "." || $file === ".." || $this->startsWith( $file, '.ht' ) ) { if ($file === "." || $file === ".." || $this->startsWith($file, '.ht')) {
return true; return true;
} }
if ( in_array( $file, $this->ignore ) ) { if (in_array($file, $this->ignore)) {
return true; return true;
} }
foreach ( $this->ignoreRE as $re ) { foreach ($this->ignoreRE as $re) {
if ( preg_match( $re, $file ) ) { if (preg_match($re, $file)) {
return true; return true;
} }
} }
return false; return false;
} }
public function readDir( $path ) { public function readDir($path) {
$content = array(); $content = array();
if ( is_dir( $path ) ) { if (is_dir($path)) {
if ( $dir = opendir( $path ) ) { if ($dir = opendir($path)) {
while ( ( $file = readdir( $dir ) ) !== false ) { while (($file = readdir($dir)) !== false) {
if ( ! $this->ignoreThisFile( $file ) ) { if (!$this->ignoreThisFile($file)) {
$content[] = $file; $content[] = $file;
} }
} }
closedir( $dir ); closedir($dir);
} }
} }
return $content; return $content;
} }
public function getLabel( $absHref ) { public function getLabel($absHref) {
return $absHref === "/" ? $this->domain : rawurldecode( basename( $absHref ) ); return $absHref === "/" ? $this->domain : rawurldecode(basename($absHref));
} }
public function normalizePath( $path, $endWithSlash ) { public function normalizePath($path, $endWithSlash) {
return ( $path === "/" ) ? "/" : ( preg_replace( '#/$#', '', $path ) . ( $endWithSlash ? "/" : "" ) ); return ($path === "/") ? "/" : (preg_replace('#/$#', '', $path) . ($endWithSlash ? "/" : ""));
} }
public function startsWith( $sequence, $start ) { public function startsWith($sequence, $start) {
return strcasecmp( substr( $sequence, 0, strlen( $start ) ), $start ) === 0; return strcasecmp(substr($sequence, 0, strlen($start)), $start) === 0;
} }
public function endsWith( $sequence, $end ) { public function endsWith($sequence, $end) {
return strcasecmp( substr( $sequence, -strlen( $end ) ), $end ) === 0; return strcasecmp(substr($sequence, -strlen($end)), $end) === 0;
} }
public function getHttpCode( $absHref ) { public function getHttpCode($absHref) {
return $this->cachedHttpCode( $absHref ); return $this->cachedHttpCode($absHref);
#return $this->fetchHttpCode( $absHref ); #return $this->fetchHttpCode($absHref);
#return $this->guessHttpCode( $absHref ); #return $this->guessHttpCode($absHref);
} }
public function cachedHttpCode( $absHref ) { public function cachedHttpCode($absHref) {
$cached = $this->cache->get( $absHref ); $cached = $this->cache->get($absHref);
if ( $cached === false ) { if ($cached === false) {
$folderStatus = $this->options["options"]["folderStatus"]; $folderStatus = $this->options["options"]["folderStatus"];
if ( array_key_exists( $absHref, $folderStatus ) ) { if (array_key_exists($absHref, $folderStatus)) {
$code = $folderStatus[$absHref]; $code = $folderStatus[$absHref];
} else { } else {
$code = $this->fetchHttpCode( $absHref ); $code = $this->fetchHttpCode($absHref);
} }
$cached = array( "href" => $absHref, "code" => $code ); $cached = array("href" => $absHref, "code" => $code);
$this->cache->set( $absHref, $cached ); $this->cache->set($absHref, $cached);
} }
return $cached["code"]; return $cached["code"];
} }
public function fetchHttpCode( $absHref ) { public function fetchHttpCode($absHref) {
$contentType = "Content-Type:"; $contentType = "Content-Type:";
$h5aiContentType = "Content-Type: text/html;h5ai="; $h5aiContentType = "Content-Type: text/html;h5ai=";
$host = getenv( "HTTP_HOST" ); $host = getenv("HTTP_HOST");
$port = getenv( "SERVER_PORT" ); $port = getenv("SERVER_PORT");
$msg = "HEAD $absHref HTTP/1.1\r\nHost: $host\r\nConnection: Close\r\n\r\n"; $msg = "HEAD $absHref HTTP/1.1\r\nHost: $host\r\nConnection: Close\r\n\r\n";
$errno = ""; $errno = "";
$errstr = ""; $errstr = "";
$socket = fsockopen( $host, $port, $errno, $errstr, 30 ); $socket = fsockopen($host, $port, $errno, $errstr, 30);
if( $socket === 0 ) { if($socket === 0) {
return null; return null;
} }
fwrite( $socket, $msg ); fwrite($socket, $msg);
$content = fgets( $socket ); $content = fgets($socket);
$code = intval( trim( substr( $content, 9, 4 ) ) ); $code = intval(trim(substr($content, 9, 4)));
if ( $code === 200 ) { if ($code === 200) {
while ( ! $this->startsWith( $content, $contentType ) ) { while (! $this->startsWith($content, $contentType)) {
$content = fgets( $socket ); $content = fgets($socket);
} }
if ( $this->startsWith( $content, $h5aiContentType ) ) { if ($this->startsWith($content, $h5aiContentType)) {
$code = "h5ai"; $code = "h5ai";
} }
} }
fclose( $socket ); fclose($socket);
return $code; return $code;
} }
public function guessHttpCode( $absHref ) { public function guessHttpCode($absHref) {
$indexFiles = array( "index.html", "index.cgi", "index.pl", "index.php", "index.xhtml", "index.htm" ); $indexFiles = array("index.html", "index.cgi", "index.pl", "index.php", "index.xhtml", "index.htm");
$absPath = $this->getAbsPath( $absHref ); $absPath = $this->getAbsPath($absHref);
$files = $this->readDir( $absPath ); $files = $this->readDir($absPath);
foreach ( $files as $file ) { foreach ($files as $file) {
if ( in_array( $file, $indexFiles ) ) { if (in_array($file, $indexFiles)) {
return 200; return 200;
} }
} }
return "h5ai"; return "h5ai";
} }
} }
?> ?>

View File

@@ -2,22 +2,22 @@
require_once "h5ai.php"; require_once "h5ai.php";
function getHttpCodes( $h5ai, $hrefs ) { function getHttpCodes($h5ai, $hrefs) {
$codes = array(); $codes = array();
foreach ( $hrefs as $href ) { foreach ($hrefs as $href) {
$href = trim( $href ); $href = trim($href);
if ( strlen( $href ) > 0 ) { if (strlen($href) > 0) {
$codes[$href] = $h5ai->getHttpCode( $href ); $codes[$href] = $h5ai->getHttpCode($href);
} }
} }
return $codes; return $codes;
} }
$h5ai = new H5ai(); $h5ai = new H5ai();
$hrefs = preg_split( "/;/", array_key_exists( "hrefs", $_REQUEST ) ? $_REQUEST[ "hrefs" ] : "" ); $hrefs = preg_split("/;/", array_key_exists("hrefs", $_REQUEST) ? $_REQUEST[ "hrefs" ] : "");
$codes = getHttpCodes( $h5ai, $hrefs ); $codes = getHttpCodes($h5ai, $hrefs);
echo count( $codes ) === 0 ? "{}" : json_encode( $codes ); echo count($codes) === 0 ? "{}" : json_encode($codes);
?> ?>

View File

@@ -2,201 +2,201 @@
class Image { class Image {
private $sourceFile; private $sourceFile;
private $source; private $source;
private $width; private $width;
private $height; private $height;
private $type; private $type;
private $dest; private $dest;
public static function isUsable() { public static function isUsable() {
return GD_VERSION != "GD_VERSION"; return GD_VERSION != "GD_VERSION";
} }
public function __construct( $filename = null ) { public function __construct($filename = null) {
$this->sourceFile = null; $this->sourceFile = null;
$this->source = null; $this->source = null;
$this->width = null; $this->width = null;
$this->height = null; $this->height = null;
$this->type = null; $this->type = null;
$this->dest = null; $this->dest = null;
$this->setSource( $filename ); $this->setSource($filename);
} }
public function __destruct() { public function __destruct() {
$this->releaseSource(); $this->releaseSource();
$this->releaseDest(); $this->releaseDest();
} }
public function setSource( $filename ) { public function setSource($filename) {
$this->releaseSource(); $this->releaseSource();
$this->releaseDest(); $this->releaseDest();
if ( is_null( $filename ) ) if (is_null($filename))
return; return;
$this->sourceFile = $filename; $this->sourceFile = $filename;
list( $this->width, $this->height, $this->type ) = getimagesize( $this->sourceFile ); list($this->width, $this->height, $this->type) = getimagesize($this->sourceFile);
$this->source = imagecreatefromstring( file_get_contents( $this->sourceFile ) ); $this->source = imagecreatefromstring(file_get_contents($this->sourceFile));
} }
public function showDest() { public function showDest() {
if ( !is_null( $this->dest ) ) { if (!is_null($this->dest)) {
header( "Content-type: image/jpeg" ); header("Content-type: image/jpeg");
imagejpeg( $this->dest, null, 100 ); imagejpeg($this->dest, null, 100);
} }
} }
public function saveDest( $filename ) { public function saveDest($filename) {
if ( !is_null( $this->dest ) ) { if (!is_null($this->dest)) {
@imagejpeg( $this->dest, $filename, 90 ); @imagejpeg($this->dest, $filename, 90);
@chmod( $filename, 0775 ); @chmod($filename, 0775);
} }
} }
public function releaseDest() { public function releaseDest() {
if ( !is_null( $this->dest ) ) { if (!is_null($this->dest)) {
imagedestroy( $this->dest ); imagedestroy($this->dest);
$this->dest = null; $this->dest = null;
} }
} }
public function releaseSource() { public function releaseSource() {
if ( !is_null( $this->source ) ) { if (!is_null($this->source)) {
imagedestroy( $this->source ); imagedestroy($this->source);
$this->sourceFile = null; $this->sourceFile = null;
$this->source = null; $this->source = null;
$this->width = null; $this->width = null;
$this->height = null; $this->height = null;
$this->type = null; $this->type = null;
} }
} }
public static function showImage( $filename ) { public static function showImage($filename) {
$image = file_get_contents( $filename ); $image = file_get_contents($filename);
header( "content-type: image" ); header("content-type: image");
echo $image; echo $image;
} }
private function magic( $destX, $destY, $srcX, $srcY, $destWidth, $destHeight, $srcWidth, $srcHeight, $canWidth = null, $canHeight = null, $color = null ) { private function magic($destX, $destY, $srcX, $srcY, $destWidth, $destHeight, $srcWidth, $srcHeight, $canWidth = null, $canHeight = null, $color = null) {
if ( !is_null( $canWidth ) && !is_null( $canHeight ) ) { if (!is_null($canWidth) && !is_null($canHeight)) {
$this->dest = imagecreatetruecolor( $canWidth, $canHeight ); $this->dest = imagecreatetruecolor($canWidth, $canHeight);
} else { } else {
$this->dest = imagecreatetruecolor( $destWidth, $destHeight ); $this->dest = imagecreatetruecolor($destWidth, $destHeight);
} }
if ( is_null( $color ) ) { if (is_null($color)) {
$color = array( 255, 255, 255 ); $color = array(255, 255, 255);
} }
$icol = imagecolorallocate( $this->dest, $color[0], $color[1], $color[2] ); $icol = imagecolorallocate($this->dest, $color[0], $color[1], $color[2]);
imagefill( $this->dest, 0, 0, $icol ); imagefill($this->dest, 0, 0, $icol);
imagecopyresampled( $this->dest, $this->source, $destX, $destY, $srcX, $srcY, $destWidth, $destHeight, $srcWidth, $srcHeight ); imagecopyresampled($this->dest, $this->source, $destX, $destY, $srcX, $srcY, $destWidth, $destHeight, $srcWidth, $srcHeight);
} }
public function thumb( $mode, $width, $height = null, $color = null ) { public function thumb($mode, $width, $height = null, $color = null) {
if ( $height === null ) { if ($height === null) {
$height = $width; $height = $width;
} }
if ( $mode === "square" ) { if ($mode === "square") {
$this->squareThumb( $width ); $this->squareThumb($width);
} elseif ( $mode === "rational" ) { } elseif ($mode === "rational") {
$this->rationalThumb( $width, $height ); $this->rationalThumb($width, $height);
} elseif ( $mode === "center" ) { } elseif ($mode === "center") {
$this->centerThumb( $width, $height, $color ); $this->centerThumb($width, $height, $color);
} else { } else {
$this->freeThumb( $width, $height ); $this->freeThumb($width, $height);
} }
} }
public function squareThumb( $width ) { public function squareThumb($width) {
$a = min( $this->width, $this->height ); $a = min($this->width, $this->height);
$x = intval( ( $this->width - $a ) / 2 ); $x = intval(($this->width - $a) / 2);
$y = intval( ( $this->height - $a ) / 2 ); $y = intval(($this->height - $a) / 2);
$this->magic( 0, 0, $x, $y, $width, $width, $a, $a ); $this->magic(0, 0, $x, $y, $width, $width, $a, $a);
} }
public function rationalThumb( $width, $height ) { public function rationalThumb($width, $height) {
$r = 1.0 * $this->width / $this->height; $r = 1.0 * $this->width / $this->height;
$h = $height; $h = $height;
$w = $r * $h; $w = $r * $h;
if ( $w > $width ) { if ($w > $width) {
$w = $width; $w = $width;
$h = 1.0 / $r * $w; $h = 1.0 / $r * $w;
} }
$w = intval( $w ); $w = intval($w);
$h = intval( $h ); $h = intval($h);
$this->magic( 0, 0, 0, 0, $w, $h, $this->width, $this->height ); $this->magic(0, 0, 0, 0, $w, $h, $this->width, $this->height);
} }
public function centerThumb( $width, $height, $color = null ) { public function centerThumb($width, $height, $color = null) {
$r = 1.0 * $this->width / $this->height; $r = 1.0 * $this->width / $this->height;
$h = $height; $h = $height;
$w = $r * $h; $w = $r * $h;
if ( $w > $width ) { if ($w > $width) {
$w = $width; $w = $width;
$h = 1.0 / $r * $w; $h = 1.0 / $r * $w;
} }
$w = intval( $w ); $w = intval($w);
$h = intval( $h ); $h = intval($h);
$x = intval( ( $width - $w ) / 2 ); $x = intval(($width - $w) / 2);
$y = intval( ( $height - $h ) / 2 ); $y = intval(($height - $h) / 2);
$this->magic( $x, $y, 0, 0, $w, $h, $this->width, $this->height, $width, $height, $color ); $this->magic($x, $y, 0, 0, $w, $h, $this->width, $this->height, $width, $height, $color);
} }
public function freeThumb( $width, $height ) { public function freeThumb($width, $height) {
$w = intval( $width ); $w = intval($width);
$h = intval( $height ); $h = intval($height);
$this->magic( 0, 0, 0, 0, $w, $h, $this->width, $this->height ); $this->magic(0, 0, 0, 0, $w, $h, $this->width, $this->height);
} }
} }
?> ?>

View File

@@ -7,9 +7,9 @@ require_once "extended.php";
require_once "tree.php"; require_once "tree.php";
$h5ai = new H5ai(); $h5ai = new H5ai();
$crumb = new Crumb( $h5ai ); $crumb = new Crumb($h5ai);
$customize = new Customize( $h5ai ); $customize = new Customize($h5ai);
$extended = new Extended( $h5ai ); $extended = new Extended($h5ai);
$tree = new Tree( $h5ai ); $tree = new Tree($h5ai);
?> ?>

View File

@@ -1,26 +1,26 @@
<?php <?php
require_once "thumbnail.php"; require_once "thumbnail.php";
$src = $_REQUEST["src"]; $src = $_REQUEST["src"];
$width = $_REQUEST["width"]; $width = $_REQUEST["width"];
$height = $_REQUEST["height"]; $height = $_REQUEST["height"];
$mode = $_REQUEST["mode"]; $mode = $_REQUEST["mode"];
if ( !Thumbnail::isUsable() ) { if (!Thumbnail::isUsable()) {
Image::showImage( $src ); Image::showImage($src);
exit; exit;
} }
$thumbnail = new Thumbnail( $src, $mode, $width, $height ); $thumbnail = new Thumbnail($src, $mode, $width, $height);
$thumbnail->create( 1 ); $thumbnail->create(1);
if ( file_exists( $thumbnail->getPath() ) ) { if (file_exists($thumbnail->getPath())) {
Image::showImage( $thumbnail->getPath() ); Image::showImage($thumbnail->getPath());
} else { } else {
$image = new Image(); $image = new Image();
$image->setSource( $src ); $image->setSource($src);
$image->thumb( $mode, $width, $height ); $image->thumb($mode, $width, $height);
$image->showDest(); $image->showDest();
} }
?> ?>

View File

@@ -4,53 +4,53 @@ require_once "image.php";
class Thumbnail { class Thumbnail {
private $src, $width, $height, $name, $href, $path; private $src, $width, $height, $name, $href, $path;
public static function isUsable() { public static function isUsable() {
return Image::isUsable(); return Image::isUsable();
} }
public function __construct( $src, $mode, $width, $height ) { public function __construct($src, $mode, $width, $height) {
$this->src = $src; $this->src = $src;
$this->width = $width; $this->width = $width;
$this->height = $height; $this->height = $height;
$this->mode = $mode; $this->mode = $mode;
$this->name = sha1( "$this->src-$this->width-$this->height-$this->mode" ); $this->name = sha1("$this->src-$this->width-$this->height-$this->mode");
$this->href = "/h5ai/cache/thumb-" . $this->name . ".jpg"; $this->href = "/h5ai/cache/thumb-" . $this->name . ".jpg";
$this->path = getenv( "DOCUMENT_ROOT" ) . $this->href; $this->path = getenv("DOCUMENT_ROOT") . $this->href;
$this->liveHref = "/h5ai/php/thumb.php?src=" . $this->src . "&width=" . $this->width . "&height=" . $this->height . "&mode=" . $this->mode; $this->liveHref = "/h5ai/php/thumb.php?src=" . $this->src . "&width=" . $this->width . "&height=" . $this->height . "&mode=" . $this->mode;
} }
public function create( $force = 0 ) { public function create($force = 0) {
if ( if (
$force === 2 $force === 2
|| ( $force === 1 && !file_exists( $this->path ) ) || ($force === 1 && !file_exists($this->path))
|| ( file_exists( $this->path ) && filemtime( $this->src ) >= filemtime( $this->path ) ) || (file_exists($this->path) && filemtime($this->src) >= filemtime($this->path))
) { ) {
$image = new Image(); $image = new Image();
$image->setSource( $this->src ); $image->setSource($this->src);
$image->thumb( $this->mode, $this->width, $this->height ); $image->thumb($this->mode, $this->width, $this->height);
$image->saveDest( $this->path ); $image->saveDest($this->path);
} }
} }
public function getHref() { public function getHref() {
return $this->href; return $this->href;
} }
public function getPath() { public function getPath() {
return $this->path; return $this->path;
} }
public function getLiveHref() { public function getLiveHref() {
return $this->liveHref; return $this->liveHref;
} }
} }
?> ?>

View File

@@ -1,146 +1,146 @@
<?php <?php
class TreeEntry { class TreeEntry {
private $h5ai, $label, $absPath, $absHref, $isFolder, $type, $content; private $h5ai, $label, $absPath, $absHref, $isFolder, $type, $content;
public function __construct( $h5ai, $absPath, $absHref, $type = null ) { public function __construct($h5ai, $absPath, $absHref, $type = null) {
$this->h5ai = $h5ai; $this->h5ai = $h5ai;
$this->label = $this->h5ai->getLabel( $absHref ); $this->label = $this->h5ai->getLabel($absHref);
$this->absPath = $this->h5ai->normalizePath( $absPath, false ); $this->absPath = $this->h5ai->normalizePath($absPath, false);
$this->isFolder = is_dir( $this->absPath ); $this->isFolder = is_dir($this->absPath);
$this->absHref = $this->h5ai->normalizePath( $absHref, $this->isFolder ); $this->absHref = $this->h5ai->normalizePath($absHref, $this->isFolder);
$this->type = $type !== null ? $type : ( $this->isFolder ? "folder" : $this->h5ai->getType( $this->absPath ) ); $this->type = $type !== null ? $type : ($this->isFolder ? "folder" : $this->h5ai->getType($this->absPath));
$this->content = null; $this->content = null;
} }
public function loadContent() { public function loadContent() {
$this->content = array(); $this->content = array();
if ( $this->h5ai->getHttpCode( $this->absHref ) !== "h5ai" ) { if ($this->h5ai->getHttpCode($this->absHref) !== "h5ai") {
return; return;
} }
$files = $this->h5ai->readDir( $this->absPath ); $files = $this->h5ai->readDir($this->absPath);
foreach ( $files as $file ) { foreach ($files as $file) {
$tree = new TreeEntry( $this->h5ai, $this->absPath . "/" . $file, $this->absHref . rawurlencode( $file ) ); $tree = new TreeEntry($this->h5ai, $this->absPath . "/" . $file, $this->absHref . rawurlencode($file));
if ( $tree->isFolder ) { if ($tree->isFolder) {
$this->content[$tree->absPath] = $tree; $this->content[$tree->absPath] = $tree;
} }
} }
$this->sort(); $this->sort();
} }
public function cmpTrees( $t1, $t2 ) { public function cmpTrees($t1, $t2) {
if ( $t1->isFolder && !$t2->isFolder ) { if ($t1->isFolder && !$t2->isFolder) {
return -1; return -1;
} }
if ( !$t1->isFolder && $t2->isFolder ) { if (!$t1->isFolder && $t2->isFolder) {
return 1; return 1;
} }
return strcasecmp( $t1->absPath, $t2->absPath ); return strcasecmp($t1->absPath, $t2->absPath);
} }
public function sort() { public function sort() {
if ( $this->content !== null ) { if ($this->content !== null) {
uasort( $this->content, array( $this, "cmpTrees" ) ); uasort($this->content, array($this, "cmpTrees"));
} }
} }
public function toHtml() { public function toHtml() {
$classes = "entry " . $this->type . ( $this->absHref === $this->h5ai->getAbsHref() ? " current" : "" ); $classes = "entry " . $this->type . ($this->absHref === $this->h5ai->getAbsHref() ? " current" : "");
$img = $this->type; $img = $this->type;
if ( $this->absHref === "/" ) { if ($this->absHref === "/") {
$img = "folder-home"; $img = "folder-home";
} }
$hint = ""; $hint = "";
$code = "h5ai"; $code = "h5ai";
if ( $this->isFolder ) { if ($this->isFolder) {
$code = $this->h5ai->getHttpCode( $this->absHref ); $code = $this->h5ai->getHttpCode($this->absHref);
$classes .= " checkedHttpCode"; $classes .= " checkedHttpCode";
if ( $code !== "h5ai" ) { if ($code !== "h5ai") {
if ( $code === 200 ) { if ($code === 200) {
$img = "folder-page"; $img = "folder-page";
$hint = "<span class='hint'><img src='/h5ai/images/page.png' alt='page' /></span>"; $hint = "<span class='hint'><img src='/h5ai/images/page.png' alt='page' /></span>";
} else { } else {
$classes .= " error"; $classes .= " error";
$hint = "<span class='hint'> " . $code . " </span>"; $hint = "<span class='hint'> " . $code . " </span>";
} }
} }
} }
$html = "<div class='" . $classes ."'>\n"; $html = "<div class='" . $classes ."'>\n";
if ( $this->content !== null && count( $this->content ) === 0 || $code !== "h5ai" ) { if ($this->content !== null && count($this->content) === 0 || $code !== "h5ai") {
$html .= "<span class='blank'></span>\n"; $html .= "<span class='blank'></span>\n";
} else { } else {
$indicatorState = $this->content === null ? " unknown" : " open"; $indicatorState = $this->content === null ? " unknown" : " open";
$html .= "<span class='indicator" . $indicatorState . "'><img src='/h5ai/images/tree.png' alt='>' /></span>\n"; $html .= "<span class='indicator" . $indicatorState . "'><img src='/h5ai/images/tree.png' alt='>' /></span>\n";
} }
$html .= "<a href='" . $this->absHref . "'>\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='icon'><img src='/h5ai/icons/16x16/" . $img . ".png' alt='" . $img . "' /></span>\n";
$html .= "<span class='label'>" . $this->label . "</span>" . $hint . "\n"; $html .= "<span class='label'>" . $this->label . "</span>" . $hint . "\n";
$html .= "</a>\n"; $html .= "</a>\n";
$html .= $this->contentToHtml(); $html .= $this->contentToHtml();
$html .= "</div>\n"; $html .= "</div>\n";
return $html; return $html;
} }
public function contentToHtml() { public function contentToHtml() {
$html = "<ul class='content'>\n"; $html = "<ul class='content'>\n";
if ( $this->content !== null ) { if ($this->content !== null) {
foreach( $this->content as $tree ) { foreach($this->content as $tree) {
$html .= "<li>" . $tree->toHtml() . "</li>"; $html .= "<li>" . $tree->toHtml() . "</li>";
} }
} }
$html .= "</ul>\n"; $html .= "</ul>\n";
return $html; return $html;
} }
public function getRoot() { public function getRoot() {
if ( $this->absHref === "/" ) { if ($this->absHref === "/") {
return $this; return $this;
}; };
$tree = new TreeEntry( $this->h5ai, dirname( $this->absPath ), dirname( $this->absHref ) ); $tree = new TreeEntry($this->h5ai, dirname($this->absPath), dirname($this->absHref));
$tree->loadContent(); $tree->loadContent();
$tree->content[ $this->absPath ] = $this; $tree->content[ $this->absPath ] = $this;
return $tree->getRoot(); return $tree->getRoot();
} }
} }
class Tree { class Tree {
private $h5ai; private $h5ai;
public function __construct( $h5ai ) { public function __construct($h5ai) {
$this->h5ai = $h5ai; $this->h5ai = $h5ai;
} }
public function toHtml() { public function toHtml() {
$options = $this->h5ai->getOptions(); $options = $this->h5ai->getOptions();
if ( $options["showTree"] === false ) { if ($options["showTree"] === false) {
return ""; return "";
} }
$tree = new TreeEntry( $this->h5ai, $this->h5ai->getAbsPath(), $this->h5ai->getAbsHref() ); $tree = new TreeEntry($this->h5ai, $this->h5ai->getAbsPath(), $this->h5ai->getAbsHref());
$tree->loadContent(); $tree->loadContent();
$root = $tree->getRoot(); $root = $tree->getRoot();
return "<section id='tree'>\n" . $root->toHtml() . "</section>\n"; return "<section id='tree'>\n" . $root->toHtml() . "</section>\n";
} }
} }

View File

@@ -1,7 +1,7 @@
<?php <?php
if ( ! array_key_exists( "href", $_REQUEST ) ) { if (!array_key_exists("href", $_REQUEST)) {
exit; exit;
} }
require_once "h5ai.php"; require_once "h5ai.php";
@@ -9,10 +9,10 @@ require_once "tree.php";
$h5ai = new H5ai(); $h5ai = new H5ai();
$absHref = trim( $_REQUEST[ "href" ] ); $absHref = trim($_REQUEST[ "href" ]);
$absPath = $h5ai->getAbsPath( $absHref ); $absPath = $h5ai->getAbsPath($absHref);
$tree = new TreeEntry( $h5ai, $absPath, $absHref ); $tree = new TreeEntry($h5ai, $absPath, $absHref);
$tree->loadContent(); $tree->loadContent();
echo $tree->contentToHtml(); echo $tree->contentToHtml();

View File

@@ -0,0 +1,24 @@
<?php
if (!array_key_exists("hrefs", $_REQUEST)) {
echo "failed";
exit;
}
require_once "h5ai.php";
require_once "zipit.php";
$h5ai = new H5ai();
$zipit = new ZipIt($h5ai);
$files = explode(":", trim($_REQUEST["hrefs"]));
$zipFile = $zipit->zip($files);
header("Content-Disposition: attachment; filename=\"h5ai-selection.zip\"");
header("Content-Type: application/force-download");
header("Content-Length: " . filesize($zipFile));
header("Connection: close");
readfile($zipFile);
?>

57
src/h5ai/php/zipit.php Normal file
View File

@@ -0,0 +1,57 @@
<?php
class ZipIt {
private $h5ai;
public function __construct($h5ai) {
$this->h5ai = $h5ai;
}
public function zip($hrefs) {
$zipFile = tempnam("/tmp", "h5ai-download");
$zip = new ZipArchive();
if (!$zip->open($zipFile, ZIPARCHIVE::CREATE)) {
return false;
}
foreach ($hrefs as $href) {
$localFile = $this->h5ai->getAbsPath($href);
$file = preg_replace("!^" . $this->h5ai->getDocRoot() . "!", "", $localFile);
if (is_dir($localFile)) {
$this->zipDir($zip, $localFile, $file);
} else {
$this->zipFile($zip, $localFile, $file);
}
}
$zip->close();
return $zipFile;
}
private function zipFile($zip, $localFile, $file) {
if (is_readable($localFile)) {
$zip->addFile($localFile, $file);
}
}
private function zipDir($zip, $localDir, $dir) {
$zip->addEmptyDir($dir);
$files = $this->h5ai->readDir($localDir);
foreach ($files as $file) {
$localFile = $localDir . "/" . $file;
$file = $dir . "/" . $file;
if (is_dir($localFile)) {
$this->zipDir($zip, $localFile, $file);
} else {
$this->zipFile($zip, $localFile, $file);
}
}
}
}
?>