Merge branch 'develop'
33
README.md
@ -1,6 +1,6 @@
|
||||
# h5ai
|
||||
|
||||
Don't use files from this repository (`src` folder) for installation.
|
||||
Please don't use files from this repository (`src` folder) for installation.
|
||||
They need to be preprocessed/compiled to work correctly. You'll find a
|
||||
precompiled package on the [project page](http://larsjung.de/h5ai).
|
||||
|
||||
@ -17,18 +17,47 @@ h5ai is provided under the terms of the [MIT License](http://github.com/lrsjng/h
|
||||
## h5ai profits from these great projects
|
||||
|
||||
* [AmplifyJS](http://amplifyjs.com) (MIT/GPL)
|
||||
* [Datejs](http://www.datejs.com) (MIT)
|
||||
* [Faenza icon set](http://tiheum.deviantart.com/art/Faenza-Icons-173323228) (GPL)
|
||||
* [HTML5 ★ Boilerplate](http://html5boilerplate.com)
|
||||
* [jQuery](http://jquery.com) (MIT/GPL)
|
||||
* [jQuery.fracs](http://larsjung.de/fracs) (MIT)
|
||||
* [jQuery.mousewheel](http://github.com/brandonaaron/jquery-mousewheel) (MIT)
|
||||
* [modernizr](http://www.modernizr.com) (MIT/BSD)
|
||||
* [Moment.js](http://momentjs.com) (MIT)
|
||||
* [qrcode](http://www.d-project.com/qrcode/index.html) (MIT)
|
||||
* [underscore.js](http://underscorejs.org) (MIT)
|
||||
|
||||
|
||||
## Changelog
|
||||
|
||||
|
||||
### v0.19 - *2012-04-??*
|
||||
|
||||
* adds lots of config options
|
||||
* changes in `config.js` and `h5ai.htaccess`
|
||||
* fixes js problems in IE 7+8
|
||||
* hides broken tree view in IE < 9, adds a message to the footer
|
||||
* removes hash changes since they break logical browser history
|
||||
* fixes thumbnail size for portrait images in icon view
|
||||
* fixes problems with file type recognition
|
||||
* adds an info page at `/_h5ai`
|
||||
* sort order is preserved while browsing
|
||||
* removes PHP error messages on thumbnail generation
|
||||
* fixes PHP some problems with packed download
|
||||
* adds support for tarred downloads
|
||||
* changes crumb image for folders with an index file
|
||||
* adds `index.php` to use h5ai in non-Apache environments
|
||||
* switches from [Datejs](http://www.datejs.com) to [Moment.js](http://momentjs.com)
|
||||
* adds [underscore.js](http://underscorejs.org)
|
||||
* fixes mousewheel problems, updates [jQuery.mousewheel](http://github.com/brandonaaron/jquery-mousewheel) to 3.0.6
|
||||
* updates lv translation
|
||||
* adds ro translation by [Jakob Cosoroabă](http://github.com/midday)
|
||||
* adds ja translation by [metasta](http://github.com/metasta)
|
||||
* adds nb translation by [Sindre Sorhus](http://github.com/sindresorhus)
|
||||
* adds sr translation by [Goran](http://github.com/vBm)
|
||||
* adds gr translation by [xhmikosr](http://github.com/xhmikosr)
|
||||
|
||||
|
||||
### v0.18 - *2012-02-24*
|
||||
|
||||
* adds optional QRCode display
|
||||
|
@ -3,7 +3,7 @@ custom = true
|
||||
|
||||
# project
|
||||
project.name = h5ai
|
||||
project.version = 0.18
|
||||
project.version = 0.19
|
||||
|
||||
|
||||
# src
|
||||
@ -18,4 +18,5 @@ release.dir = release
|
||||
# tools
|
||||
tool.wepp = wepp
|
||||
tool.jslint = jslint
|
||||
tool.jshint = jshint
|
||||
|
||||
|
16
build.xml
@ -54,6 +54,11 @@
|
||||
<jslint files="${build.dir}/_h5ai/js/inc/main.js" />
|
||||
</target>
|
||||
|
||||
<target name="hint" depends="build-prepare">
|
||||
<wepp file="${build.dir}/_h5ai/js/inc/main.js" tofile="${build.dir}/_h5ai/js/inc/main.js" />
|
||||
<jshint files="${build.dir}/_h5ai/js/inc/main.js" />
|
||||
</target>
|
||||
|
||||
|
||||
<macrodef name="wepp-args">
|
||||
<attribute name="args" default="" />
|
||||
@ -77,7 +82,6 @@
|
||||
<attribute name="tofile" />
|
||||
<sequential>
|
||||
<wepp-args args="--inFile '@{file}' --outFile '@{toFile}'" />
|
||||
<bytes file="@{file}" toFile="@{toFile}" />
|
||||
</sequential>
|
||||
</macrodef>
|
||||
|
||||
@ -113,4 +117,14 @@
|
||||
</sequential>
|
||||
</macrodef>
|
||||
|
||||
<macrodef name="jshint">
|
||||
<attribute name="files" />
|
||||
<sequential>
|
||||
<echo>JSHint @{files}</echo>
|
||||
<exec executable="${tool.jshint}" failonerror="false">
|
||||
<arg line="@{files}" />
|
||||
</exec>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
|
||||
</project>
|
||||
|
@ -1,5 +1,4 @@
|
||||
|
||||
|
||||
Options -Indexes
|
||||
|
||||
AddType text/html .php
|
||||
@ -9,6 +8,7 @@ AddType text/html .php
|
||||
# if php doesn't get interpreted try to
|
||||
# uncomment one of the following lines
|
||||
###########################################
|
||||
|
||||
#AddHandler application/x-httpd-php .php
|
||||
#AddHandler application/x-httpd-php5 .php
|
||||
#AddHandler application/x-httpd-php52 .php
|
||||
@ -19,19 +19,19 @@ AddType text/html .php
|
||||
#AddHandler php53-script .php
|
||||
|
||||
|
||||
# cache images, css and js for 52 weeks
|
||||
# cache images, css and js for 7 days
|
||||
<IfModule headers_module>
|
||||
<FilesMatch "\.png$">
|
||||
Header set Cache-Control "max-age=31449600, public"
|
||||
Header set Cache-Control "max-age=604800, public"
|
||||
</FilesMatch>
|
||||
<FilesMatch "\.css$">
|
||||
Header set Cache-Control "max-age=31449600, public"
|
||||
Header set Cache-Control "max-age=604800, public"
|
||||
</FilesMatch>
|
||||
<FilesMatch "\.js$">
|
||||
Header set Cache-Control "max-age=31449600, public"
|
||||
Header set Cache-Control "max-age=604800, public"
|
||||
</FilesMatch>
|
||||
<FilesMatch "thumb-.*\.jpg$">
|
||||
Header set Cache-Control "max-age=31449600, public"
|
||||
Header set Cache-Control "max-age=604800, public"
|
||||
</FilesMatch>
|
||||
</IfModule>
|
||||
|
||||
|
@ -17,16 +17,17 @@ var H5AI_CONFIG = {
|
||||
"h5aiAbsHref": "/_h5ai/",
|
||||
|
||||
/*
|
||||
* Filenames of customized header and footer files to look for
|
||||
* in each folder. For Example:
|
||||
*
|
||||
* "customHeader": "_h5ai.header.html",
|
||||
* "customFooter": "_h5ai.footer.html",
|
||||
*
|
||||
* This is disabled by default.
|
||||
* Spacing of the main content.
|
||||
* Left and right will be added to a minimum of 30px. Top and bottom
|
||||
* are calculated relative to the top and bottom bar heights.
|
||||
*/
|
||||
"customHeader": null,
|
||||
"customFooter": null,
|
||||
"spacing": {
|
||||
"maxWidth": 960,
|
||||
"top": 50,
|
||||
"right": "auto",
|
||||
"bottom": 50,
|
||||
"left": "auto"
|
||||
},
|
||||
|
||||
/*
|
||||
* An array of view modes the user may choose from. Currently there
|
||||
@ -35,8 +36,111 @@ var H5AI_CONFIG = {
|
||||
* view mode is fixed and the selector buttons are hidden.
|
||||
* The user selected view mode is also stored local in modern browsers
|
||||
* so that it will be persistent.
|
||||
*
|
||||
* Set parent folder labels to real folder names.
|
||||
*/
|
||||
"viewmodes": ["details", "icons"],
|
||||
"view": {
|
||||
"modes": ["details", "icons"],
|
||||
"setParentFolderLabels": true
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Extensions in alphabetical order.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Show a clickable breadcrumb.
|
||||
*/
|
||||
"crumb": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
/*
|
||||
* Filenames of customized header and footer files to look for
|
||||
* in each folder.
|
||||
*/
|
||||
"custom": {
|
||||
"enabled": false,
|
||||
"header": "_h5ai.header.html",
|
||||
"footer": "_h5ai.footer.html"
|
||||
},
|
||||
|
||||
/*
|
||||
* EXPLICITLY: USE "shell" ON YOUR OWN RISK.
|
||||
*
|
||||
* Requires PHP on the server.
|
||||
* Enable packaged download of selected entries.
|
||||
* Execution: "php", "shell".
|
||||
* Supported formats: "tar", "zip".
|
||||
*/
|
||||
"download": {
|
||||
"enabled": false,
|
||||
"execution": "shell",
|
||||
"format": "zip"
|
||||
},
|
||||
|
||||
/*
|
||||
* Allow filtering the displayed files and folders.
|
||||
* Note: filters will be treated as JavaScript regular expressions
|
||||
* if you prefix them with "re:".
|
||||
*/
|
||||
"filter": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
/*
|
||||
* Associative array of folders and their HTTP status codes to
|
||||
* avoid HEAD requests to that folders. The key (folder) must start
|
||||
* and end with a slash (/).
|
||||
* For example
|
||||
* "/some/folder/": 200
|
||||
* will always return HTTP status 200 (OK), which will be interpreted
|
||||
* as a non auto indexed folder, that means a folder containing an
|
||||
* appropriate default index file.
|
||||
*/
|
||||
"folderstatus": {
|
||||
"enabled": false,
|
||||
"folders": {}
|
||||
},
|
||||
|
||||
/*
|
||||
* Localization, for example "en", "de" etc. - see "langs" below for
|
||||
* possible values. Adjust it to your needs. If lang is not found in
|
||||
* "langs" it defaults to "en".
|
||||
*
|
||||
* Optionally try to use browser language, falls back to previous
|
||||
* specified language.
|
||||
*/
|
||||
"l10n": {
|
||||
"enabled": true,
|
||||
"lang": "en",
|
||||
"useBrowserLang": true
|
||||
},
|
||||
|
||||
/*
|
||||
* Link the hover effects between crumb, main view and tree.
|
||||
*/
|
||||
"link-hover-states": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
/*
|
||||
* Show QRCodes on hovering files.
|
||||
*/
|
||||
"qrcode": {
|
||||
"enabled": false,
|
||||
"size": 150
|
||||
},
|
||||
|
||||
/*
|
||||
* Make entries selectable. At the moment only needed for packaged download.
|
||||
*/
|
||||
"select": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
/*
|
||||
* Default sort order is a two letter code. The first letter specifies
|
||||
@ -44,162 +148,126 @@ var H5AI_CONFIG = {
|
||||
* second letter specifies the sort order: "a" for "ascending" or "d"
|
||||
* for "descending".
|
||||
*/
|
||||
"sortorder": "na",
|
||||
"sort": {
|
||||
"enabled": true,
|
||||
"order": "na"
|
||||
},
|
||||
|
||||
/*
|
||||
* Show a folder tree, boolean.
|
||||
* Show additional info in a statusbar.
|
||||
*/
|
||||
"statusbar": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
/*
|
||||
* Requires PHP on the server.
|
||||
* Show thumbnails for image files. Needs the "/_h5ai/cache" folder to be
|
||||
* writable for the Apache Server.
|
||||
*/
|
||||
"thumbnails": {
|
||||
"enabled": true,
|
||||
"types": ["bmp", "gif", "ico", "image", "jpg", "png", "tiff"],
|
||||
"delay": 1000
|
||||
},
|
||||
|
||||
/*
|
||||
* Replace window title with current breadcrumb.
|
||||
*/
|
||||
"title": {
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
/*
|
||||
* Show a folder tree.
|
||||
* Note that this tree might have side effects as it sends HEAD requests
|
||||
* to the folders, and therefore will invoke index.php scripts. Use
|
||||
* folderStatus below to avoid such requests.
|
||||
* "folderstatus" above to avoid such requests.
|
||||
* It might also affect performance significantly.
|
||||
*
|
||||
* Slide tree bar into viewport if there is enough space.
|
||||
*/
|
||||
"showTree": true,
|
||||
|
||||
/*
|
||||
* Slide tree bar into viewport if there is enough space, boolean.
|
||||
*/
|
||||
"slideTree": true,
|
||||
|
||||
/*
|
||||
* Associative array of folders and their HTTP status codes to
|
||||
* avoid HEAD requests to that folders. The key (folder) must start
|
||||
* and end with a slash (/).
|
||||
* For example:
|
||||
* "/some/folder/": 200
|
||||
* will always return HTTP status 200 (OK), which will be interpreted
|
||||
* as a non auto indexed folder, that means a folder containing an
|
||||
* appropriate default index file.
|
||||
*/
|
||||
"folderStatus": {},
|
||||
|
||||
/*
|
||||
* Localization, for example "en", "de" etc. - see h5aiLangs below for
|
||||
* possible values. Adjust it to your needs. If lang is not found in
|
||||
* h5aiLangs it defaults to "en".
|
||||
*/
|
||||
"lang": "en",
|
||||
|
||||
/*
|
||||
* Try to use browser language, falls back to previous specified lang.
|
||||
*/
|
||||
"useBrowserLang": true,
|
||||
|
||||
/*
|
||||
* Set parent folder labels to real folder names.
|
||||
*/
|
||||
"setParentFolderLabels": true,
|
||||
|
||||
/*
|
||||
* Link the hover effects between crumb, extended view and tree.
|
||||
*/
|
||||
"linkHoverStates": true,
|
||||
|
||||
/*
|
||||
* Date format in detailed view, for example: "yyyy-MM-dd HH:mm:ss"
|
||||
* Syntax as specified by date.js
|
||||
* http://code.google.com/p/datejs/wiki/FormatSpecifiers
|
||||
*/
|
||||
"dateFormat": "yyyy-MM-dd HH:mm",
|
||||
|
||||
/*
|
||||
* Requires PHP on the server.
|
||||
* Show thumbnails for image files.
|
||||
*/
|
||||
"showThumbs": true,
|
||||
"thumbTypes": ["bmp", "gif", "ico", "image", "jpg", "png", "tiff"],
|
||||
|
||||
/*
|
||||
* Requires PHP on the server.
|
||||
* Enable zipped download of selected entries.
|
||||
*/
|
||||
"zippedDownload": false,
|
||||
|
||||
/*
|
||||
* Show QRCodes on hovering files.
|
||||
* Set this to the desired size in pixel or null to not display QRCodes.
|
||||
* A good size to start with might be 150.
|
||||
*/
|
||||
"qrCodesSize": null,
|
||||
|
||||
/*
|
||||
* Allow filtering the displayed files and folders.
|
||||
* Filters are ment to be JavaScript regular expressions.
|
||||
*/
|
||||
"showFilter": false
|
||||
"tree": {
|
||||
"enabled": true,
|
||||
"slide": true
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* File types mapped to file extensions.
|
||||
* File types mapped to file extensions. In alphabetical order.
|
||||
*/
|
||||
"types": {
|
||||
"archive": [".tar.bz2", ".tar.gz", ".tgz"],
|
||||
"audio": [".aif", ".m4a", ".mid", ".mp3", ".mpa", ".ra", ".ogg", ".wav", ".wma"],
|
||||
"authors": ["authors"],
|
||||
"bin": [".class", ".o", ".so"],
|
||||
"blank": [],
|
||||
"bmp": [".bmp"],
|
||||
"c": [".c"],
|
||||
"calc": [".ods", ".ots", ".xlr", ".xls", ".xlsx"],
|
||||
"cd": [".cue", ".iso"],
|
||||
"copying": ["copying", "license"],
|
||||
"cpp": [".cpp"],
|
||||
"css": [".css", ".less"],
|
||||
"deb": [".deb"],
|
||||
"default": [],
|
||||
"doc": [".doc", ".docx", ".odm", ".odt", ".ott"],
|
||||
"draw": [".drw"],
|
||||
"eps": [".eps"],
|
||||
"exe": [".exe"],
|
||||
"folder": [],
|
||||
"folder-home": [],
|
||||
"folder-open": [],
|
||||
"folder-page": [],
|
||||
"folder-parent": [],
|
||||
"gif": [".gif"],
|
||||
"gzip": [".gz"],
|
||||
"h": [".h"],
|
||||
"hpp": [".hpp"],
|
||||
"html": [".htm", ".html", ".shtml"],
|
||||
"ico": [".ico"],
|
||||
"image": [".xpm"],
|
||||
"install": ["install"],
|
||||
"java": [".java"],
|
||||
"jpg": [".jpg", ".jpeg"],
|
||||
"js": [".js", ".json"],
|
||||
"log": [".log", "changelog"],
|
||||
"makefile": [".pom", "build.xml", "pom.xml"],
|
||||
"package": [],
|
||||
"pdf": [".pdf"],
|
||||
"php": [".php"],
|
||||
"playlist": [".m3u"],
|
||||
"png": [".png"],
|
||||
"pres": [".odp", ".otp", ".pps", ".ppt", ".pptx"],
|
||||
"psd": [".psd"],
|
||||
"py": [".py"],
|
||||
"rar": [".rar"],
|
||||
"rb": [".rb"],
|
||||
"readme": ["readme"],
|
||||
"rpm": [".rpm"],
|
||||
"rss": [".rss"],
|
||||
"rtf": [".rtf"],
|
||||
"script": [".conf", ".csh", ".ini", ".ksh", ".sh", ".shar", ".tcl"],
|
||||
"source": [],
|
||||
"sql": [],
|
||||
"tar": [".tar"],
|
||||
"tex": [".tex"],
|
||||
"text": [".markdown", ".md", ".text", ".txt"],
|
||||
"tiff": [".tiff"],
|
||||
"unknown": [],
|
||||
"vcal": [".vcal"],
|
||||
"video": [".avi", ".flv", ".mov", ".mp4", ".mpg", ".rm", ".swf", ".vob", ".wmv"],
|
||||
"xml": [".xml"],
|
||||
"zip": [".bz2", ".jar", ".war", ".z", ".Z", ".zip"]
|
||||
"archive": [".tar.bz2", ".tar.gz", ".tgz"],
|
||||
"audio": [".aif", ".flac", ".m4a", ".mid", ".mp3", ".mpa", ".ra", ".ogg", ".wav", ".wma"],
|
||||
"authors": ["authors"],
|
||||
"bin": [".class", ".o", ".so"],
|
||||
"blank": [],
|
||||
"bmp": [".bmp"],
|
||||
"c": [".c"],
|
||||
"calc": [".ods", ".ots", ".xlr", ".xls", ".xlsx"],
|
||||
"cd": [".cue", ".iso"],
|
||||
"copying": ["copying", "license"],
|
||||
"cpp": [".cpp"],
|
||||
"css": [".css", ".less"],
|
||||
"deb": [".deb"],
|
||||
"default": [],
|
||||
"doc": [".doc", ".docx", ".odm", ".odt", ".ott"],
|
||||
"draw": [".drw"],
|
||||
"eps": [".eps"],
|
||||
"exe": [".bat", ".cmd", ".exe"],
|
||||
"folder": [],
|
||||
"folder-home": [],
|
||||
"folder-open": [],
|
||||
"folder-page": [],
|
||||
"folder-parent": [],
|
||||
"gif": [".gif"],
|
||||
"gzip": [".gz"],
|
||||
"h": [".h"],
|
||||
"hpp": [".hpp"],
|
||||
"html": [".htm", ".html", ".shtml"],
|
||||
"ico": [".ico"],
|
||||
"image": [".xpm"],
|
||||
"install": ["install"],
|
||||
"java": [".java"],
|
||||
"jpg": [".jpg", ".jpeg"],
|
||||
"js": [".js", ".json"],
|
||||
"log": [".log", "changelog"],
|
||||
"makefile": [".pom", "build.xml", "pom.xml"],
|
||||
"package": [],
|
||||
"pdf": [".pdf"],
|
||||
"php": [".php"],
|
||||
"playlist": [".m3u", ".m3u8", ".pls"],
|
||||
"png": [".png"],
|
||||
"pres": [".odp", ".otp", ".pps", ".ppt", ".pptx"],
|
||||
"psd": [".psd"],
|
||||
"py": [".py"],
|
||||
"rar": [".rar"],
|
||||
"rb": [".rb"],
|
||||
"readme": ["readme"],
|
||||
"rpm": [".rpm"],
|
||||
"rss": [".rss"],
|
||||
"rtf": [".rtf"],
|
||||
"script": [".conf", ".csh", ".ini", ".ksh", ".sh", ".shar", ".tcl"],
|
||||
"source": [],
|
||||
"sql": [],
|
||||
"tar": [".tar"],
|
||||
"tex": [".tex"],
|
||||
"text": [".diff", ".markdown", ".md", ".patch", ".text", ".txt"],
|
||||
"tiff": [".tiff"],
|
||||
"unknown": [],
|
||||
"vcal": [".vcal"],
|
||||
"video": [".avi", ".flv", ".mkv", ".mov", ".mp4", ".mpg", ".rm", ".swf", ".vob", ".wmv"],
|
||||
"xml": [".xml"],
|
||||
"zip": [".7z", ".bz2", ".jar", ".lzma", ".war", ".z", ".Z", ".zip"]
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* Available translations.
|
||||
* Available translations. "en" in first place as a reference, otherwise in alphabetical order.
|
||||
*
|
||||
* Date format is used in detailed view, for example: "YYYY-MM-DD HH:mm:ss"
|
||||
* Syntax as specified by Moment.js (http://momentjs.com)
|
||||
*/
|
||||
"langs": {
|
||||
|
||||
@ -215,7 +283,8 @@ var H5AI_CONFIG = {
|
||||
"folders": "folders",
|
||||
"files": "files",
|
||||
"download": "download",
|
||||
"noMatch": "no match"
|
||||
"noMatch": "no match",
|
||||
"dateFormat": "YYYY-MM-DD HH:mm"
|
||||
},
|
||||
|
||||
"bg": {
|
||||
@ -228,9 +297,7 @@ var H5AI_CONFIG = {
|
||||
"parentDirectory": "Предходна директория",
|
||||
"empty": "празно",
|
||||
"folders": "папки",
|
||||
"files": "файлове",
|
||||
"download": "download",
|
||||
"noMatch": "no match"
|
||||
"files": "файлове"
|
||||
},
|
||||
|
||||
"cs": {
|
||||
@ -243,9 +310,7 @@ var H5AI_CONFIG = {
|
||||
"parentDirectory": "Nadřazený adresář",
|
||||
"empty": "prázdný",
|
||||
"folders": "složek",
|
||||
"files": "souborů",
|
||||
"download": "download",
|
||||
"noMatch": "no match"
|
||||
"files": "souborů"
|
||||
},
|
||||
|
||||
"de": {
|
||||
@ -260,7 +325,8 @@ var H5AI_CONFIG = {
|
||||
"folders": "Ordner",
|
||||
"files": "Dateien",
|
||||
"download": "Download",
|
||||
"noMatch": "keine Treffer"
|
||||
"noMatch": "keine Treffer",
|
||||
"dateFormat": "DD.MM.YYYY HH:mm"
|
||||
},
|
||||
|
||||
"es": {
|
||||
@ -274,8 +340,7 @@ var H5AI_CONFIG = {
|
||||
"empty": "vacío",
|
||||
"folders": "Directorios",
|
||||
"files": "Archivos",
|
||||
"download": "Descargar",
|
||||
"noMatch": "no match"
|
||||
"download": "Descargar"
|
||||
},
|
||||
|
||||
"fr": {
|
||||
@ -290,7 +355,22 @@ var H5AI_CONFIG = {
|
||||
"folders": "Répertoires",
|
||||
"files": "Fichiers",
|
||||
"download": "télécharger",
|
||||
"noMatch": "no match"
|
||||
"noMatch": "rien trouvé"
|
||||
},
|
||||
|
||||
"gr": {
|
||||
"lang": "ελληνικά",
|
||||
"details": "Λεπτομέρειες",
|
||||
"icons": "Εικονίδια",
|
||||
"name": "Όνομα",
|
||||
"lastModified": "Τελευταία Τροποποίηση",
|
||||
"size": "Μέγεθος",
|
||||
"parentDirectory": "Προηγούμενος Κατάλογος",
|
||||
"empty": "κενό",
|
||||
"folders": "Φάκελοι",
|
||||
"files": "Αρχεία",
|
||||
"download": "Μεταμόρφωση",
|
||||
"noMatch": "Κανένα Ταίριασμα"
|
||||
},
|
||||
|
||||
"it": {
|
||||
@ -303,10 +383,23 @@ var H5AI_CONFIG = {
|
||||
"parentDirectory": "Cartella Superiore",
|
||||
"empty": "vuota",
|
||||
"folders": "cartelle",
|
||||
"files": "file",
|
||||
"download": "download",
|
||||
"noMatch": "no match"
|
||||
},
|
||||
"files": "file"
|
||||
},
|
||||
|
||||
"ja": {
|
||||
"lang": "日本語",
|
||||
"details": "詳細",
|
||||
"icons": "アイコン",
|
||||
"name": "名前",
|
||||
"lastModified": "変更日",
|
||||
"size": "サイズ",
|
||||
"parentDirectory": "親フォルダ",
|
||||
"empty": "項目なし",
|
||||
"folders": "フォルダ",
|
||||
"files": "ファイル",
|
||||
"download": "ダウンロード",
|
||||
"noMatch": "一致なし"
|
||||
},
|
||||
|
||||
"lv": {
|
||||
"lang": "latviešu",
|
||||
@ -320,7 +413,22 @@ var H5AI_CONFIG = {
|
||||
"folders": "mapes",
|
||||
"files": "faili",
|
||||
"download": "lejupielādēt",
|
||||
"noMatch": "no match"
|
||||
"noMatch": "nav sakritības"
|
||||
},
|
||||
|
||||
"nb": {
|
||||
"lang": "norwegian",
|
||||
"details": "detaljer",
|
||||
"icons": "ikoner",
|
||||
"name": "Navn",
|
||||
"lastModified": "Sist endret",
|
||||
"size": "Størrelse",
|
||||
"parentDirectory": "Overordnet mappe",
|
||||
"empty": "tom",
|
||||
"folders": "mapper",
|
||||
"files": "filer",
|
||||
"download": "last ned",
|
||||
"noMatch": "ingen treff"
|
||||
},
|
||||
|
||||
"nl": {
|
||||
@ -331,11 +439,7 @@ var H5AI_CONFIG = {
|
||||
"lastModified": "Laatste wijziging",
|
||||
"size": "Grootte",
|
||||
"parentDirectory": "Bovenliggende map",
|
||||
"empty": "lege",
|
||||
"folders": "folders",
|
||||
"files": "files",
|
||||
"download": "download",
|
||||
"noMatch": "no match"
|
||||
"empty": "lege"
|
||||
},
|
||||
|
||||
"pl": {
|
||||
@ -348,9 +452,7 @@ var H5AI_CONFIG = {
|
||||
"parentDirectory": "Katalog nadrzędny",
|
||||
"empty": "pusty",
|
||||
"folders": "foldery",
|
||||
"files": "pliki",
|
||||
"download": "download",
|
||||
"noMatch": "no match"
|
||||
"files": "pliki"
|
||||
},
|
||||
|
||||
"pt": {
|
||||
@ -363,9 +465,22 @@ var H5AI_CONFIG = {
|
||||
"parentDirectory": "Diretório superior",
|
||||
"empty": "vazio",
|
||||
"folders": "pastas",
|
||||
"files": "arquivos",
|
||||
"download": "download",
|
||||
"noMatch": "no match"
|
||||
"files": "arquivos"
|
||||
},
|
||||
|
||||
"ro": {
|
||||
"lang": "română",
|
||||
"details": "detalii",
|
||||
"icons": "pictograme",
|
||||
"name": "nume",
|
||||
"lastModified": "ultima modificare",
|
||||
"size": "mărime",
|
||||
"parentDirectory": "dosar părinte",
|
||||
"empty": "gol",
|
||||
"folders": "dosar",
|
||||
"files": "fişiere",
|
||||
"download": "descarcă",
|
||||
"noMatch": "0 rezultate"
|
||||
},
|
||||
|
||||
"ru": {
|
||||
@ -378,9 +493,7 @@ var H5AI_CONFIG = {
|
||||
"parentDirectory": "Главная директория",
|
||||
"empty": "пусто",
|
||||
"folders": "папки",
|
||||
"files": "файлы",
|
||||
"download": "download",
|
||||
"noMatch": "no match"
|
||||
"files": "файлы"
|
||||
},
|
||||
|
||||
"sk": {
|
||||
@ -393,9 +506,22 @@ var H5AI_CONFIG = {
|
||||
"parentDirectory": "Nadriadený priečinok",
|
||||
"empty": "prázdny",
|
||||
"folders": "priečinkov",
|
||||
"files": "súborov",
|
||||
"files": "súborov"
|
||||
},
|
||||
|
||||
"sr": {
|
||||
"lang": "srpski",
|
||||
"details": "detalji",
|
||||
"icons": "ikone",
|
||||
"name": "Ime",
|
||||
"lastModified": "Poslednja modifikacija",
|
||||
"size": "Veličina",
|
||||
"parentDirectory": "Roditeljski direktorijum",
|
||||
"empty": "prazno",
|
||||
"folders": "direktorijum",
|
||||
"files": "fajlovi",
|
||||
"download": "download",
|
||||
"noMatch": "no match"
|
||||
"noMatch": "bez poklapanja"
|
||||
},
|
||||
|
||||
"sv": {
|
||||
@ -406,11 +532,7 @@ var H5AI_CONFIG = {
|
||||
"lastModified": "Senast ändrad",
|
||||
"size": "Filstorlek",
|
||||
"parentDirectory": "Till överordnad mapp",
|
||||
"empty": "tom",
|
||||
"folders": "folders",
|
||||
"files": "files",
|
||||
"download": "download",
|
||||
"noMatch": "no match"
|
||||
"empty": "tom"
|
||||
},
|
||||
|
||||
"tr": {
|
||||
@ -424,8 +546,7 @@ var H5AI_CONFIG = {
|
||||
"empty": "boş",
|
||||
"folders": "klasörler",
|
||||
"files": "dosyalar",
|
||||
"download": "indir",
|
||||
"noMatch": "no match"
|
||||
"download": "indir"
|
||||
},
|
||||
|
||||
"zh-cn": {
|
||||
@ -439,8 +560,7 @@ var H5AI_CONFIG = {
|
||||
"empty": "空文件夹",
|
||||
"folders": "文件夹",
|
||||
"files": "文件",
|
||||
"download": "下载",
|
||||
"noMatch": "no match"
|
||||
"download": "下载"
|
||||
},
|
||||
|
||||
"zh-tw": {
|
||||
@ -454,8 +574,7 @@ var H5AI_CONFIG = {
|
||||
"empty": "空資料夾",
|
||||
"folders": "資料夾",
|
||||
"files": "檔案",
|
||||
"download": "下載",
|
||||
"noMatch": "no match"
|
||||
"download": "下載"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -14,7 +14,7 @@ $H5AI_CONFIG = array(
|
||||
* This configuration assumes that h5ai is installed
|
||||
* in the webroot directory of the Apache server.
|
||||
*/
|
||||
"ROOT_ABS_PATH" => safe_dirname(safe_dirname(__FILE__)),
|
||||
"ROOT_ABS_PATH" => dirname(dirname(__FILE__)),
|
||||
|
||||
/*
|
||||
* Files/folders that should not be listed. Specified
|
||||
|
@ -1,33 +1,32 @@
|
||||
|
||||
#table {
|
||||
#data-apache-autoindex {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
|
||||
table {
|
||||
display: block;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
|
||||
th, td {
|
||||
padding: 3px 6px;
|
||||
padding: 6px;
|
||||
text-align: left;
|
||||
border: none;
|
||||
}
|
||||
th {
|
||||
padding-bottom: 18px;
|
||||
opacity: 0.4;
|
||||
.transition(all 0.2s ease-in-out);
|
||||
|
||||
&:hover, &:hover a {
|
||||
color: #555;
|
||||
cursor: pointer;
|
||||
opacity: 0.9;
|
||||
}
|
||||
a, a:visited {
|
||||
color: #555;
|
||||
font-weight: normal;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
opacity: 0.4;
|
||||
.transition(all 0.2s ease-in-out);
|
||||
|
||||
img {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
padding: 0 8px;
|
||||
&:hover {
|
||||
color: #555;
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -35,6 +34,20 @@
|
||||
border: 1px solid #ddd;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
font-size: 16px;
|
||||
|
||||
a, a:active, a:visited {
|
||||
display: block;
|
||||
color: #555;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #e80;
|
||||
}
|
||||
}
|
||||
}
|
||||
td:nth-child(1), th:nth-child(1) {
|
||||
text-align: center;
|
||||
@ -43,26 +56,23 @@
|
||||
img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
padding-top: 2px;
|
||||
position: relative;
|
||||
top: -2px;
|
||||
}
|
||||
}
|
||||
td:nth-child(2), th:nth-child(2) {
|
||||
width: 682px;
|
||||
max-width: 682px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
td:nth-child(3), th:nth-child(3) {
|
||||
text-align: right;
|
||||
width: 160px;
|
||||
min-width: 160px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
td:nth-child(4), th:nth-child(4) {
|
||||
text-align: right;
|
||||
width: 70px;
|
||||
min-width: 70px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
67
src/_h5ai/css/inc/bottombar.less
Normal file
@ -0,0 +1,67 @@
|
||||
|
||||
#bottombar {
|
||||
position: fixed;
|
||||
z-index: 5;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 6px 0 8px 0;
|
||||
.vert-gradient(rgb(241,241,241), rgb(228,228,228));
|
||||
border-top: 1px solid rgb(210,210,210);
|
||||
|
||||
color: #999;
|
||||
text-align: center;
|
||||
|
||||
a, a:active, a:visited {
|
||||
color: #555;
|
||||
text-decoration: none;
|
||||
.transition(all 0.2s ease-in-out);
|
||||
opacity: 0.7;
|
||||
|
||||
&:hover {
|
||||
color: #e80;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.left {
|
||||
display: block;
|
||||
padding: 0 8px;
|
||||
float: left
|
||||
}
|
||||
.center {
|
||||
display: block;
|
||||
margin: 0 100px;
|
||||
}
|
||||
.right {
|
||||
display: block;
|
||||
padding: 0 8px;
|
||||
float: right
|
||||
}
|
||||
.noJsMsg {
|
||||
color: #c33;
|
||||
margin-left: 16px;
|
||||
}
|
||||
.oldBrowser {
|
||||
display: none;
|
||||
color: #c33;
|
||||
margin-left: 16px;
|
||||
a, a:active, a:visited {
|
||||
color: #c33;
|
||||
text-decoration: underline;
|
||||
&:hover {
|
||||
color: #e80;
|
||||
}
|
||||
}
|
||||
}
|
||||
.status {
|
||||
.sep {
|
||||
display: inline-block;
|
||||
padding: 0 6px;
|
||||
}
|
||||
&.default {
|
||||
}
|
||||
&.dynamic {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,18 +1,31 @@
|
||||
|
||||
#content {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
margin: 50px auto;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
> header {
|
||||
display: none;
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 80px;
|
||||
border-bottom: 2px dashed #ddd;
|
||||
}
|
||||
> footer {
|
||||
display: none;
|
||||
padding-top: 10px;
|
||||
margin-top: 80px;
|
||||
border-top: 2px dashed #ddd;
|
||||
|
||||
#content-header, #content-footer {
|
||||
|
||||
a, a:active, a:visited {
|
||||
color: #2080FF;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #68A9FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#content-header {
|
||||
padding-bottom: 12px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
#content-footer {
|
||||
padding-top: 12px;
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
30
src/_h5ai/css/inc/download.less
Normal file
@ -0,0 +1,30 @@
|
||||
|
||||
#download {
|
||||
display: none;
|
||||
.topbar-right;
|
||||
.transition(all 0.2s ease-in-out);
|
||||
|
||||
&.failed {
|
||||
background-color: rgba(255,0,0,0.5);
|
||||
}
|
||||
}
|
||||
|
||||
#download-auth {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 5;
|
||||
left: 0;
|
||||
top: 0;
|
||||
.vert-gradient(rgb(241,241,241), rgb(228,228,228));
|
||||
border: 1px solid rgb(210,210,210);
|
||||
|
||||
input {
|
||||
display: block;
|
||||
margin: 4px 6px;
|
||||
border: 1px solid rgb(210,210,210);
|
||||
font-family: Ubuntu, sans-serif;
|
||||
color: #555;
|
||||
background-color: rgba(255,255,255,1);
|
||||
width: 100px;
|
||||
}
|
||||
}
|
@ -13,6 +13,8 @@
|
||||
clear: both;
|
||||
|
||||
&.header {
|
||||
font-size: 13px;
|
||||
|
||||
a, a:active, a:visited {
|
||||
padding-bottom: 18px;
|
||||
color: #555;
|
||||
@ -42,7 +44,6 @@
|
||||
}
|
||||
}
|
||||
&.entry {
|
||||
|
||||
a, a:active, a:visited {
|
||||
display: block;
|
||||
color: #555;
|
||||
@ -54,10 +55,10 @@
|
||||
background-color: #f6f6f6;
|
||||
color: #e80;
|
||||
}
|
||||
&.selected:not(.selecting), &.selecting:not(.selected) {
|
||||
border-color: rgba(240,100,0,0.2);
|
||||
background-color: rgba(240,100,0,0.2);
|
||||
}
|
||||
}
|
||||
&.selected:not(.selecting) a, &.selecting:not(.selected) a {
|
||||
border-color: rgba(240,100,0,0.2);
|
||||
background-color: rgba(240,100,0,0.2);
|
||||
}
|
||||
&.error {
|
||||
a, a:active, a:visited {
|
||||
@ -102,7 +103,7 @@
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
&.thumb {
|
||||
border: 1px solid #eee;
|
||||
// border: 1px solid #ddd;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,18 +133,6 @@
|
||||
width: 80px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
&.entry.thumb .icon.small {
|
||||
overflow: hidden;
|
||||
padding: 5px;
|
||||
|
||||
img {
|
||||
background-color: #eee;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 1px solid #ddd;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.empty, .no-match {
|
||||
@ -206,19 +195,15 @@
|
||||
border-color: #eee;
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
&.selected:not(.selecting), &.selecting:not(.selected) {
|
||||
border-color: rgba(240,100,0,0.2);
|
||||
background-color: rgba(240,100,0,0.2);
|
||||
}
|
||||
.icon {
|
||||
display: block;
|
||||
|
||||
img {
|
||||
min-width: 48px;
|
||||
min-height: 48px;
|
||||
max-width: 100px;
|
||||
height: 48px;
|
||||
margin-bottom: 8px;
|
||||
&.thumb {
|
||||
border: 1px solid #eee;
|
||||
// border: 1px solid #ddd;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -233,6 +218,10 @@
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
&.selected:not(.selecting) a, &.selecting:not(.selected) a {
|
||||
border-color: rgba(240,100,0,0.2);
|
||||
background-color: rgba(240,100,0,0.2);
|
||||
}
|
||||
&.error {
|
||||
a, a:active, a:visited {
|
||||
color: #aaa;
|
||||
@ -253,21 +242,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
&.entry.thumb .icon.big {
|
||||
width: 100px;
|
||||
height: 58px;
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
background-color: #eee;
|
||||
min-width: 46px;
|
||||
min-height: 46px;
|
||||
min-width: 12px;
|
||||
min-height: 12px;
|
||||
border: 1px solid #ddd;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.empty, .no-match {
|
||||
|
19
src/_h5ai/css/inc/filter.less
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
#filter {
|
||||
.topbar-right;
|
||||
|
||||
input {
|
||||
display: none;
|
||||
border: none;
|
||||
font-family: Ubuntu, sans-serif;
|
||||
color: #555;
|
||||
background-color: rgba(0,0,0,0);
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
&.current {
|
||||
input {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
|
||||
body > footer {
|
||||
position: fixed;
|
||||
z-index: 5;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 6px 0 8px 0;
|
||||
.vert-gradient(rgb(241,241,241), rgb(228,228,228));
|
||||
border-top: 1px solid rgb(210,210,210);
|
||||
|
||||
color: #999;
|
||||
font-size: 0.85em;
|
||||
text-align: center;
|
||||
|
||||
a, a:active, a:visited {
|
||||
color: #555;
|
||||
text-decoration: none;
|
||||
.transition(all 0.2s ease-in-out);
|
||||
opacity: 0.7;
|
||||
|
||||
&:hover {
|
||||
color: #e80;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.left {
|
||||
display: block;
|
||||
padding: 0 8px;
|
||||
float: left
|
||||
}
|
||||
.center {
|
||||
display: block;
|
||||
margin: 0 100px;
|
||||
}
|
||||
.right {
|
||||
display: block;
|
||||
padding: 0 8px;
|
||||
float: right
|
||||
}
|
||||
.noJsMsg {
|
||||
color: #c33;
|
||||
margin-left: 16px;
|
||||
}
|
||||
.status {
|
||||
.sep {
|
||||
display: inline-block;
|
||||
padding: 0 6px;
|
||||
}
|
||||
&.default {
|
||||
}
|
||||
&.dynamic {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
#langSelector {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
.langOptions {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
overflow: auto;
|
||||
display: none;
|
||||
right: 0;
|
||||
top: 0;
|
||||
max-height: 200px;
|
||||
background-color: rgb(241,241,241);
|
||||
border: 1px solid rgb(210,210,210);
|
||||
|
||||
> .scrollbar {
|
||||
margin: 0;
|
||||
width: 6px;
|
||||
background-color: rgb(210,210,210);
|
||||
|
||||
.drag {
|
||||
background-color: rgb(180,180,180);
|
||||
}
|
||||
&.dragOn .drag {
|
||||
background-color: rgb(150,150,150);
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
text-align: left;
|
||||
|
||||
li {
|
||||
padding: 8px 24px 10px 24px;
|
||||
white-space: nowrap;
|
||||
border-top: 1px solid rgb(231,231,231);
|
||||
.transition(all 0.2s ease-in-out);
|
||||
|
||||
&.current {
|
||||
color: #333;
|
||||
background-color: rgba(255,255,255,0.8);
|
||||
}
|
||||
&:hover {
|
||||
color: #e80;
|
||||
background-color: rgba(255,255,255,0.8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
63
src/_h5ai/css/inc/h5ai-info.less
Normal file
@ -0,0 +1,63 @@
|
||||
|
||||
body#h5ai-info {
|
||||
font-family: Ubuntu, Arial, sans;
|
||||
margin: 0 auto;
|
||||
font-size: 20px;
|
||||
color: #555;
|
||||
max-width: 600px;
|
||||
text-align: center;
|
||||
|
||||
.h5ai {
|
||||
font-family: 'Miltonian Tattoo';
|
||||
font-weight: normal;
|
||||
}
|
||||
h1 {
|
||||
font-size: 3.6em;
|
||||
margin: 0.9em 0 0 0;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.15em;
|
||||
margin: 2.6em 0 0 0;
|
||||
}
|
||||
p {
|
||||
line-height: 1.6em;
|
||||
}
|
||||
p + p {
|
||||
margin-top: 1.2em;
|
||||
}
|
||||
li {
|
||||
margin-top: 0.6em;
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
#tests {
|
||||
display: inline-block;
|
||||
list-style-type: none;
|
||||
text-align: left;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
.test-label {
|
||||
display: inline-block;
|
||||
width: 300px;
|
||||
}
|
||||
.test-result {
|
||||
display: inline-block;
|
||||
width: 70px;
|
||||
text-align: right;
|
||||
font-weight: bold;
|
||||
color: #aaa;
|
||||
|
||||
&.test-passed {
|
||||
color: #5a5;
|
||||
}
|
||||
&.test-failed {
|
||||
color: #a55;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#bottombar {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
53
src/_h5ai/css/inc/l10n.less
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
#langSelector {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
.langOptions {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
overflow: auto;
|
||||
display: none;
|
||||
right: 0;
|
||||
top: 0;
|
||||
max-height: 200px;
|
||||
background-color: rgb(241,241,241);
|
||||
border: 1px solid rgb(210,210,210);
|
||||
|
||||
> .scrollbar {
|
||||
margin: 0;
|
||||
width: 6px;
|
||||
background-color: rgb(210,210,210);
|
||||
|
||||
.drag {
|
||||
background-color: rgb(180,180,180);
|
||||
}
|
||||
&.dragOn .drag {
|
||||
background-color: rgb(150,150,150);
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
text-align: left;
|
||||
|
||||
li {
|
||||
padding: 8px 24px 10px 24px;
|
||||
white-space: nowrap;
|
||||
border-top: 1px solid rgb(231,231,231);
|
||||
.transition(all 0.2s ease-in-out);
|
||||
|
||||
&.current {
|
||||
color: #333;
|
||||
background-color: rgba(255,255,255,0.8);
|
||||
}
|
||||
&:hover {
|
||||
color: #e80;
|
||||
background-color: rgba(255,255,255,0.8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
|
||||
|
||||
.border-radius (@radius) {
|
||||
-webkit-border-radius: @radius; /* Saf3-4, iOS 1-3.2, Android <1.6 */
|
||||
-moz-border-radius: @radius; /* FF1-3.6 */
|
||||
@ -56,4 +55,3 @@
|
||||
-moz-background-size: @size; /* FF3.6 */
|
||||
background-size: @size; /* Opera, IE9, Saf5, Chrome, FF4 */
|
||||
}
|
||||
|
||||
|
@ -1,135 +0,0 @@
|
||||
|
||||
.nav-highlight {
|
||||
background-color: rgba(255,255,255,0.5);
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.nav-hover {
|
||||
.nav-highlight;
|
||||
color: #e80;
|
||||
}
|
||||
|
||||
@nav-sep-border: 1px solid rgba(0,0,0,0.05);
|
||||
|
||||
.nav-left {
|
||||
float: left;
|
||||
border-right: @nav-sep-border;
|
||||
}
|
||||
|
||||
.nav-right {
|
||||
float: right;
|
||||
border-left: @nav-sep-border;
|
||||
}
|
||||
|
||||
body > nav {
|
||||
position: fixed;
|
||||
z-index: 5;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
font-size: 0.85em;
|
||||
.vert-gradient(rgb(241,241,241), rgb(228,228,228));
|
||||
border-bottom: 1px solid rgb(210,210,210);
|
||||
|
||||
span.jsDisabledFallback {
|
||||
display: block;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding: 0 10px;
|
||||
color: #999;
|
||||
}
|
||||
a, a:active, a:visited, span.element {
|
||||
color: #555;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
opacity: 0.7;
|
||||
.transition(all 0.2s ease-in-out);
|
||||
|
||||
display: block;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding: 0 10px;
|
||||
|
||||
&:hover, &.hover {
|
||||
.nav-hover;
|
||||
}
|
||||
}
|
||||
.current {
|
||||
a, span.element {
|
||||
.nav-highlight;
|
||||
}
|
||||
}
|
||||
img {
|
||||
position: relative;
|
||||
top: -2px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
img + span, img + input {
|
||||
margin-left: 6px;
|
||||
}
|
||||
.crumb {
|
||||
.nav-left;
|
||||
.hint {
|
||||
margin-left: 8px;
|
||||
font-style: italic;
|
||||
color: #999;
|
||||
}
|
||||
img.hint {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
}
|
||||
.view {
|
||||
.nav-right;
|
||||
}
|
||||
#download {
|
||||
display: none;
|
||||
.nav-right;
|
||||
.transition(all 0.2s ease-in-out);
|
||||
|
||||
&.failed {
|
||||
background-color: rgba(255,0,0,0.5);
|
||||
}
|
||||
}
|
||||
#filter {
|
||||
.nav-right;
|
||||
|
||||
input {
|
||||
display: none;
|
||||
border: none;
|
||||
font-family: Ubuntu, sans-serif;
|
||||
color: #555;
|
||||
background-color: rgba(0,0,0,0);
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
&.current {
|
||||
input {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#download-auth {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 5;
|
||||
left: 0;
|
||||
top: 0;
|
||||
font-size: 0.85em;
|
||||
.vert-gradient(rgb(241,241,241), rgb(228,228,228));
|
||||
border: 1px solid rgb(210,210,210);
|
||||
|
||||
input {
|
||||
display: block;
|
||||
margin: 4px 6px;
|
||||
border: 1px solid rgb(210,210,210);
|
||||
font-family: Ubuntu, sans-serif;
|
||||
color: #555;
|
||||
background-color: rgba(255,255,255,1);
|
||||
width: 100px;
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
|
||||
@media only screen and (max-width: 500px) {
|
||||
body > nav {
|
||||
#topbar {
|
||||
.view span {
|
||||
display: none;
|
||||
}
|
||||
@ -12,7 +13,7 @@ body > nav {
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 350px) {
|
||||
body > nav {
|
||||
#topbar {
|
||||
.crumb {
|
||||
display: none;
|
||||
}
|
||||
@ -28,9 +29,29 @@ body > nav {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
body > footer {
|
||||
#bottombar {
|
||||
.center {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
a[href]:after {
|
||||
content: "";
|
||||
}
|
||||
#topbar {
|
||||
position: static;
|
||||
margin-bottom: 2em;
|
||||
.view, #download {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
#bottombar {
|
||||
position: static;
|
||||
margin-top: 2em;
|
||||
}
|
||||
#tree {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
88
src/_h5ai/css/inc/topbar.less
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
#topbar {
|
||||
position: fixed;
|
||||
z-index: 5;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
.vert-gradient(rgb(241,241,241), rgb(228,228,228));
|
||||
border-bottom: 1px solid rgb(210,210,210);
|
||||
}
|
||||
|
||||
|
||||
.topbar-highlight {
|
||||
background-color: rgba(255,255,255,0.5);
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.topbar-hover {
|
||||
.topbar-highlight;
|
||||
color: #e80;
|
||||
}
|
||||
|
||||
@topbar-sep-border: 1px solid rgba(0,0,0,0.05);
|
||||
|
||||
.topbar-left {
|
||||
float: left;
|
||||
border-right: @topbar-sep-border;
|
||||
}
|
||||
|
||||
.topbar-right {
|
||||
float: right;
|
||||
border-left: @topbar-sep-border;
|
||||
}
|
||||
|
||||
|
||||
#navbar {
|
||||
list-style: none;
|
||||
list-style-image: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
a, a:active, a:visited, span.element {
|
||||
color: #555;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
opacity: 0.7;
|
||||
.transition(all 0.2s ease-in-out);
|
||||
|
||||
display: block;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding: 0 10px;
|
||||
|
||||
&:hover, &.hover {
|
||||
.topbar-hover;
|
||||
}
|
||||
}
|
||||
.current {
|
||||
a, span.element {
|
||||
.topbar-highlight;
|
||||
}
|
||||
}
|
||||
img {
|
||||
position: relative;
|
||||
top: -2px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
img + span, img + input {
|
||||
margin-left: 6px;
|
||||
}
|
||||
.crumb {
|
||||
.topbar-left;
|
||||
.hint {
|
||||
margin-left: 8px;
|
||||
font-style: italic;
|
||||
color: #999;
|
||||
}
|
||||
img.hint {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
.view {
|
||||
.topbar-right;
|
||||
}
|
||||
}
|
@ -7,7 +7,6 @@
|
||||
height: 100%;
|
||||
z-index: 3;
|
||||
overflow: auto;
|
||||
font-size: 0.85em;
|
||||
padding: 8px;
|
||||
background-color: rgb(241,241,241);
|
||||
border-right: 2px solid rgb(221,221,221);
|
||||
@ -28,20 +27,12 @@
|
||||
}
|
||||
|
||||
.entry {
|
||||
.blank, .indicator {
|
||||
.indicator {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 25px;
|
||||
float: left;
|
||||
}
|
||||
.indicator {
|
||||
opacity: 0.7;
|
||||
.transition(all 0.2s ease-in-out);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
img {
|
||||
position: relative;
|
||||
left: 0;
|
||||
@ -52,13 +43,23 @@
|
||||
.transition(all 0.2s ease-in-out);
|
||||
}
|
||||
&.open {
|
||||
cursor: pointer;
|
||||
opacity: 0.7;
|
||||
img {
|
||||
.transform(rotate(90deg));
|
||||
}
|
||||
}
|
||||
&.close {
|
||||
cursor: pointer;
|
||||
opacity: 0.7;
|
||||
}
|
||||
&.unknown {
|
||||
cursor: pointer;
|
||||
opacity: 0.3;
|
||||
}
|
||||
&.none {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
> a, > a:active, > a.visited {
|
||||
margin-left: 16px;
|
||||
@ -92,16 +93,8 @@
|
||||
margin-left: 12px;
|
||||
font-size: 0.9em;
|
||||
color: #ccc;
|
||||
img {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.file {
|
||||
display: none;
|
||||
}
|
||||
&.current {
|
||||
> a, > a:active, > a:visited {
|
||||
border: 1px solid rgb(221,221,221);
|
||||
|
@ -1,58 +0,0 @@
|
||||
|
||||
@import "inc/h5bp-norm";
|
||||
@import "inc/mixins";
|
||||
|
||||
|
||||
body {
|
||||
font-family: Ubuntu, sans-serif;
|
||||
font-size: 16px;
|
||||
color: #555;
|
||||
background-color: #fff;
|
||||
margin: 80px 30px;
|
||||
}
|
||||
|
||||
|
||||
@import "inc/nav";
|
||||
@import "inc/content";
|
||||
@import "inc/table";
|
||||
@import "inc/extended";
|
||||
@import "inc/tree";
|
||||
@import "inc/context";
|
||||
@import "inc/footer";
|
||||
@import "inc/responsive";
|
||||
|
||||
|
||||
html.js {
|
||||
.hideOnJs {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
html.no-js {
|
||||
.hideOnNoJs {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
html.h5ai-js {
|
||||
#h5ai-reference:after {
|
||||
content: " (js)";
|
||||
}
|
||||
}
|
||||
html.h5ai-php {
|
||||
#h5ai-reference:after {
|
||||
content: " (php)";
|
||||
}
|
||||
|
||||
#table {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#tree, #content > header, #content > footer {
|
||||
display: block;
|
||||
}
|
||||
|
||||
html.no-js {
|
||||
#extended.details-view, #extended.icons-view {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
47
src/_h5ai/css/styles.less
Normal file
@ -0,0 +1,47 @@
|
||||
|
||||
@import "inc/h5bp-norm";
|
||||
@import "inc/mixins";
|
||||
|
||||
::-moz-selection { background: #68A9FF; color: #fff; text-shadow: none; }
|
||||
::selection { background: #68A9FF; color: #fff; text-shadow: none; }
|
||||
|
||||
body {
|
||||
font-family: Ubuntu, sans-serif;
|
||||
font-size: 13px;
|
||||
color: #555;
|
||||
background-color: #fff;
|
||||
margin: 30px;
|
||||
}
|
||||
|
||||
|
||||
@import "inc/topbar";
|
||||
@import "inc/download";
|
||||
@import "inc/filter";
|
||||
|
||||
@import "inc/content";
|
||||
@import "inc/extended";
|
||||
|
||||
@import "inc/bottombar";
|
||||
@import "inc/l10n";
|
||||
|
||||
@import "inc/tree";
|
||||
@import "inc/context";
|
||||
@import "inc/apache-autoindex-table";
|
||||
|
||||
@import "inc/responsive";
|
||||
|
||||
@import "inc/h5ai-info";
|
||||
|
||||
|
||||
html.js .hideOnJs, html.no-js .hideOnNoJs {
|
||||
display: none;
|
||||
}
|
||||
html.oldie {
|
||||
.oldBrowser {
|
||||
display: inline !important;
|
||||
}
|
||||
#tree {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +1,4 @@
|
||||
<!-- generated code ends here -->
|
||||
</section>
|
||||
</section>
|
||||
<div id="selection-rect"></div>
|
||||
<footer class="clearfix">
|
||||
<span class="left">
|
||||
<a id="h5ai-reference" href="http://larsjung.de/h5ai" target="_blank" title="h5ai project page">h5ai %BUILD_VERSION%</a>
|
||||
<span class="hideOnJs noJsMsg"> ⚡ JavaScript is disabled! ⚡ </span>
|
||||
</span>
|
||||
<span class="right">
|
||||
<span id="langSelector">
|
||||
<span class="lang">en</span> - <span class="l10n-lang">english</span>
|
||||
<span class="langOptions"></span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="center">
|
||||
<span class="hideOnNoJs">
|
||||
<span class="status default">
|
||||
<span class="folderTotal"></span> <span class="l10n-folders">folders</span>
|
||||
<span class='sep'>·</span>
|
||||
<span class="fileTotal"></span> <span class="l10n-files">files</span>
|
||||
</span>
|
||||
<span class="status dynamic">
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</footer>
|
||||
<script src="/_h5ai/config.js"></script>
|
||||
<script src="/_h5ai/js/libs.js"></script>
|
||||
<!-- generated code ends here -->
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
11
src/_h5ai/footer.php
Normal file
@ -0,0 +1,11 @@
|
||||
<!-- generated code ends here -->
|
||||
</div>
|
||||
<div id="data-generic-json" class="hidden">
|
||||
<?php if (stripos($_SERVER["REQUEST_METHOD"], "HEAD") === false) {
|
||||
require_once(str_replace("\\", "/", __DIR__) . "/php/inc/H5ai.php");
|
||||
$h5ai = new H5ai();
|
||||
echo $h5ai->getGenericJson();
|
||||
} ?>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -2,32 +2,39 @@
|
||||
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="h5ai-js no-js" lang="en"> <!--<![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>Directory index · styled with h5ai</title>
|
||||
<meta name="h5ai-version" content="h5ai %BUILD_VERSION% (js)">
|
||||
<meta name="description" content="Directory index styled with h5ai (http://larsjung.de/h5ai)">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="shortcut icon" type="image/png" href="/_h5ai/images/h5ai-16x16.png">
|
||||
<link rel="apple-touch-icon" type="image/png" href="/_h5ai/images/h5ai-48x48.png">
|
||||
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Ubuntu:regular,italic,bold">
|
||||
<link rel="stylesheet" href="/_h5ai/css/main.css">
|
||||
<script src="/_h5ai/js/modernizr.min.js"></script>
|
||||
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Ubuntu:regular,italic,bold">
|
||||
<link rel="stylesheet" href="/_h5ai/css/styles.css">
|
||||
<script src="/_h5ai/config.js"></script>
|
||||
<script src="/_h5ai/js/scripts.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="clearfix hideOnNoJs">
|
||||
<body id="h5ai-main">
|
||||
<div id="topbar" class="clearfix">
|
||||
<ul id="navbar"></ul>
|
||||
</nav>
|
||||
<section id="tree"></section>
|
||||
<section id="content">
|
||||
<header></header>
|
||||
<section id="extended" class="clearfix"></section>
|
||||
<footer></footer>
|
||||
<section id="table" class="hideOnJs">
|
||||
<!--
|
||||
The following code was generated by Apache's autoindex module. It is not valid HTML5, but this
|
||||
section gets removed from the DOM tree as soon as its information is parsed. The actual page
|
||||
should render as valid HTML5, even if the produced source is not valid HTML5.
|
||||
-->
|
||||
</div>
|
||||
<div id="content">
|
||||
<div id="extended" class="clearfix"></div>
|
||||
</div>
|
||||
<div id="bottombar" class="clearfix">
|
||||
<span class="left">
|
||||
<a id="h5ai-reference" href="http://larsjung.de/h5ai" title="h5ai project page">h5ai %BUILD_VERSION%</a>
|
||||
<span class="hideOnJs noJsMsg"> ⚡ JavaScript is disabled! ⚡ </span>
|
||||
<span class="oldBrowser"> ⚡ Some features disabled! Works best in <a href="http://browsehappy.com">modern browsers</a>. ⚡ </span>
|
||||
</span>
|
||||
<span class="right"></span>
|
||||
<span class="center"></span>
|
||||
</div>
|
||||
<div id="data-apache-autoindex" class="hideOnJs">
|
||||
<!--
|
||||
The following code was generated by Apache's autoindex module. It is not valid HTML5, but this
|
||||
section gets removed from the DOM tree as soon as its information is parsed. The actual page
|
||||
should render as valid HTML5, even if the produced source is not valid HTML5.
|
||||
-->
|
||||
|
@ -1,32 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="h5ai-php no-js" lang="en"> <!--<![endif]-->
|
||||
<?php include "php/main.php"; ?>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title><?php echo $h5ai->getTitle(); ?></title>
|
||||
<meta name="h5ai-version" content="h5ai %BUILD_VERSION% (php)">
|
||||
<meta name="description" content="Directory index styled with h5ai (http://larsjung.de/h5ai)">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="shortcut icon" type="image/png" href="/_h5ai/images/h5ai-16x16.png">
|
||||
<link rel="apple-touch-icon" type="image/png" href="/_h5ai/images/h5ai-48x48.png">
|
||||
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Ubuntu:regular,italic,bold">
|
||||
<link rel="stylesheet" href="/_h5ai/css/main.css">
|
||||
<script src="/_h5ai/js/modernizr.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="clearfix">
|
||||
<ul id="navbar">
|
||||
<?php echo $crumb->toHtml(); ?>
|
||||
</ul>
|
||||
</nav>
|
||||
<?php echo $tree->toHtml(); ?>
|
||||
<section id="content">
|
||||
<?php echo $customize->getHeader(); ?>
|
||||
<?php echo $extended->toHtml(); ?>
|
||||
<?php echo $customize->getFooter(); ?>
|
||||
<section id="table" class="hideOnJs">
|
||||
<!-- The following code was generated by Apache's autoindex module and gets ignored and removed from the DOM tree. -->
|
Before Width: | Height: | Size: 409 B After Width: | Height: | Size: 395 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
src/_h5ai/images/html5.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 706 B After Width: | Height: | Size: 564 B |
43
src/_h5ai/index.html
Normal file
@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js ie7 oldie" lang="en"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>h5ai %BUILD_VERSION% info page</title>
|
||||
<meta name="description" content="h5ai · a beautified Apache index">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="shortcut icon" type="image/png" href="/_h5ai/images/h5ai-16x16.png">
|
||||
<link rel="apple-touch-icon" type="image/png" href="/_h5ai/images/h5ai-48x48.png">
|
||||
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Ubuntu:regular,italic,bold">
|
||||
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Miltonian+Tattoo:regular">
|
||||
<link rel="stylesheet" href="/_h5ai/css/styles.css">
|
||||
<script src="/_h5ai/config.js"></script>
|
||||
<script src="/_h5ai/js/scripts.js"></script>
|
||||
</head>
|
||||
<body id="h5ai-info">
|
||||
<h1><span class="h5ai">h5ai</span></h1>
|
||||
version %BUILD_VERSION%
|
||||
<h2>server supports</h2>
|
||||
<ul id="tests">
|
||||
<li class="test" data-id="php"><span class="test-label">php version</span><span class="test-result">?</span></li>
|
||||
<li class="test" data-id="cache"><span class="test-label">cache</span><span class="test-result">?</span></li>
|
||||
<li class="test" data-id="thumbs"><span class="test-label">thumbnails</span><span class="test-result">?</span></li>
|
||||
<li class="test" data-id="temp"><span class="test-label">temp directory</span><span class="test-result">?</span></li>
|
||||
<li class="test" data-id="archive"><span class="test-label">php tar and zip</span><span class="test-result">?</span></li>
|
||||
<li class="test" data-id="tar"><span class="test-label">shell tar</span><span class="test-result">?</span></li>
|
||||
<li class="test" data-id="zip"><span class="test-label">shell zip</span><span class="test-result">?</span></li>
|
||||
</ul>
|
||||
<div id="bottombar" class="clearfix">
|
||||
<span class="left">
|
||||
<a id="h5ai-reference" href="http://larsjung.de/h5ai" title="h5ai project page">h5ai %BUILD_VERSION%</a>
|
||||
<span class="hideOnJs noJsMsg"> ⚡ JavaScript is disabled! ⚡ </span>
|
||||
<span class="oldBrowser"> ⚡ Some features disabled! Works best in <a href="http://browsehappy.com">modern browsers</a>. ⚡ </span>
|
||||
</span>
|
||||
<span class="right"></span>
|
||||
<span class="center"></span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,115 +0,0 @@
|
||||
|
||||
(function ($, H5AI) {
|
||||
|
||||
H5AI.connector = (function () {
|
||||
|
||||
var cache = {},
|
||||
pathnameStatusCache = {},
|
||||
contentTypeRegEx = /^text\/html;h5ai=/,
|
||||
getPath = function (folder, tableRow) {
|
||||
|
||||
var absHref = H5AI.util.getAbsHref(folder, tableRow),
|
||||
path = cache[absHref];
|
||||
|
||||
if (!path) {
|
||||
path = H5AI.Path(folder, tableRow);
|
||||
if (!path.isParentFolder) {
|
||||
cache[path.absHref] = path;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
},
|
||||
fetchStatus = function (pathname, callback) {
|
||||
|
||||
if (H5AI.core.settings.folderStatus[pathname]) {
|
||||
callback(H5AI.core.settings.folderStatus[pathname]);
|
||||
return;
|
||||
} else if (pathnameStatusCache[pathname]) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
},
|
||||
updatePath = function (path) {
|
||||
|
||||
if (path.isFolder && !path.isParentFolder && path.status === undefined) {
|
||||
fetchStatus(path.absHref, function (status) {
|
||||
|
||||
if (status !== "h5ai") {
|
||||
path.status = status;
|
||||
}
|
||||
H5AI.html.updateHtml(path);
|
||||
H5AI.core.linkHoverStates();
|
||||
});
|
||||
}
|
||||
},
|
||||
updatePaths = function () {
|
||||
|
||||
$.each(cache, function (ref, cached) {
|
||||
updatePath(cached);
|
||||
});
|
||||
},
|
||||
fetchStatusAndContent = function (pathname, includeParent, callback) {
|
||||
|
||||
fetchStatus(pathname, function (status) {
|
||||
|
||||
if (status !== "h5ai") {
|
||||
callback(status, {});
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: pathname,
|
||||
type: "GET",
|
||||
dataType: "html",
|
||||
error: function (xhr) {
|
||||
|
||||
callback(xhr.status, {}); // since it was checked before this should never happen
|
||||
},
|
||||
success: function (html, status, xhr) {
|
||||
|
||||
var content = {};
|
||||
|
||||
if (!contentTypeRegEx.test(xhr.getResponseHeader("Content-Type"))) {
|
||||
callback(xhr.status, {}); // since it was checked before this should never happen
|
||||
return;
|
||||
}
|
||||
|
||||
$(html).find("#table td").closest("tr").each(function () {
|
||||
|
||||
var path = getPath(pathname, this);
|
||||
|
||||
if (path.isFolder && (!path.isParentFolder || includeParent)) {
|
||||
content[path.absHref] = path;
|
||||
updatePath(path);
|
||||
}
|
||||
});
|
||||
callback("h5ai", content);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
getPath: getPath,
|
||||
updatePaths: updatePaths,
|
||||
fetchStatusAndContent: fetchStatusAndContent
|
||||
};
|
||||
}());
|
||||
|
||||
}(jQuery, H5AI));
|
@ -1,55 +0,0 @@
|
||||
|
||||
(function ($, H5AI) {
|
||||
|
||||
H5AI.context = (function () {
|
||||
|
||||
var $context,
|
||||
qrCodesSize,
|
||||
showQrCode = function ($a) {
|
||||
|
||||
var absHref = $a.attr('href'),
|
||||
url = 'http://' + document.domain + absHref;
|
||||
|
||||
$context.find('.qrcode').empty().qrcode({
|
||||
render: Modernizr.canvas ? 'canvas' : 'div',
|
||||
width: qrCodesSize,
|
||||
height: qrCodesSize,
|
||||
color: '#333',
|
||||
text: url
|
||||
});
|
||||
},
|
||||
init = function () {
|
||||
|
||||
qrCodesSize = H5AI.core.settings.qrCodesSize;
|
||||
if (!qrCodesSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
var hideTimeoutId = null;
|
||||
|
||||
$context = $('<div id="context"><div class="qrcode"/></div>');
|
||||
$context.appendTo('body');
|
||||
|
||||
$('#extended')
|
||||
.on('mouseenter', '.entry.file a', function () {
|
||||
|
||||
showQrCode($(this));
|
||||
clearTimeout(hideTimeoutId);
|
||||
$context.stop(true, true).fadeIn(400);
|
||||
})
|
||||
.on('mouseleave', '.entry.file a', function () {
|
||||
|
||||
hideTimeoutId = setTimeout(function () {
|
||||
|
||||
$context.stop(true, true).fadeOut(400);
|
||||
}, 200);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
init: init
|
||||
};
|
||||
}());
|
||||
|
||||
}(jQuery, H5AI));
|
@ -1,439 +0,0 @@
|
||||
|
||||
(function (window, $, H5AI, config) {
|
||||
|
||||
H5AI.core = (function () {
|
||||
|
||||
var $window = $(window),
|
||||
defaults = {
|
||||
store: {
|
||||
viewmode: "h5ai.pref.viewmode",
|
||||
lang: "h5ai.pref.lang"
|
||||
},
|
||||
callbacks: {
|
||||
pathClick: []
|
||||
},
|
||||
|
||||
rootAbsHref: "/",
|
||||
h5aiAbsHref: "/_h5ai/",
|
||||
customHeader: null,
|
||||
customFooter: null,
|
||||
viewmodes: ["details", "icons"],
|
||||
sortorder: "na",
|
||||
showTree: true,
|
||||
slideTree: true,
|
||||
folderStatus: {},
|
||||
lang: "en",
|
||||
useBrowserLang: true,
|
||||
setParentFolderLabels: true,
|
||||
linkHoverStates: true,
|
||||
dateFormat: "yyyy-MM-dd HH:mm",
|
||||
showThumbs: false,
|
||||
thumbTypes: ["bmp", "gif", "ico", "image", "jpg", "png", "tiff"],
|
||||
zippedDownload: false,
|
||||
qrCodesSize: null,
|
||||
showFilter: false
|
||||
},
|
||||
settings = $.extend({}, defaults, config.options),
|
||||
currentDateFormat = settings.dateFormat,
|
||||
extToFileType = (function (types) {
|
||||
var map = {};
|
||||
$.each(types, function (type, exts) {
|
||||
$.each(exts, function (idx, ext) {
|
||||
map[ext] = type;
|
||||
});
|
||||
});
|
||||
return map;
|
||||
}(config.types)),
|
||||
hash = function (obj) {
|
||||
|
||||
if ($.isPlainObject(obj)) {
|
||||
var hashStr = '';
|
||||
$.each($.extend({}, hash(), obj), function (key, value) {
|
||||
if (value) {
|
||||
hashStr += '/' + encodeURIComponent(key) + '=' + encodeURIComponent(value);
|
||||
}
|
||||
});
|
||||
hashStr = '#!' + hashStr;
|
||||
window.location.hash = hashStr;
|
||||
return hashStr;
|
||||
} else {
|
||||
var result = {},
|
||||
parts = document.location.hash.split('/');
|
||||
|
||||
if (parts.length >= 2 || parts[0] === '#!') {
|
||||
parts.shift();
|
||||
$.each(parts, function (idx, part) {
|
||||
|
||||
var match = /^([^=]*)=(.*?)$/.exec(part);
|
||||
if (match) {
|
||||
result[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
|
||||
}
|
||||
});
|
||||
}
|
||||
return typeof obj === 'string' ? result[obj] : result;
|
||||
}
|
||||
},
|
||||
api = function () {
|
||||
|
||||
return settings.h5aiAbsHref + "php/api.php";
|
||||
},
|
||||
image = function (id, noPngExt) {
|
||||
|
||||
return settings.h5aiAbsHref + "images/" + id + (noPngExt ? "" : ".png");
|
||||
},
|
||||
icon = function (id, big) {
|
||||
|
||||
return settings.h5aiAbsHref + "icons/" + (big ? "48x48" : "16x16") + "/" + id + ".png";
|
||||
},
|
||||
viewmode = function (viewmode) {
|
||||
|
||||
var $viewDetails = $("#viewdetails"),
|
||||
$viewIcons = $("#viewicons"),
|
||||
$extended = $("#extended");
|
||||
|
||||
if (viewmode) {
|
||||
amplify.store(settings.store.viewmode, viewmode);
|
||||
} else {
|
||||
viewmode = amplify.store(settings.store.viewmode);
|
||||
}
|
||||
viewmode = $.inArray(viewmode, settings.viewmodes) >= 0 ? viewmode : settings.viewmodes[0];
|
||||
H5AI.core.hash({view: viewmode});
|
||||
|
||||
$viewDetails.add($viewIcons).removeClass("current");
|
||||
if (viewmode === "details") {
|
||||
$viewDetails.addClass("current");
|
||||
$extended.addClass("details-view").removeClass("icons-view").show();
|
||||
} else if (viewmode === "icons") {
|
||||
$viewIcons.addClass("current");
|
||||
$extended.removeClass("details-view").addClass("icons-view").show();
|
||||
} else {
|
||||
$extended.hide();
|
||||
}
|
||||
},
|
||||
initTopSpace = function () {
|
||||
|
||||
var $body = $("body"),
|
||||
$tree = $("#tree"),
|
||||
adjustTopSpace = function () {
|
||||
|
||||
var winHeight = $window.height(),
|
||||
navHeight = $("body > nav").outerHeight(),
|
||||
footerHeight = $("body > footer").outerHeight(),
|
||||
contentSpacing = 50,
|
||||
treeSpacing = 0;
|
||||
|
||||
$body.css({
|
||||
"margin-top": navHeight + contentSpacing,
|
||||
"margin-bottom": footerHeight + contentSpacing
|
||||
});
|
||||
|
||||
$tree.css({
|
||||
top: navHeight + treeSpacing,
|
||||
height: winHeight - navHeight - footerHeight - 16 - 2 * treeSpacing
|
||||
});
|
||||
|
||||
try {
|
||||
$tree.get(0).updateScrollbar();
|
||||
} catch (err) {}
|
||||
};
|
||||
|
||||
$window.resize(function () {
|
||||
adjustTopSpace();
|
||||
});
|
||||
adjustTopSpace();
|
||||
},
|
||||
initViews = function () {
|
||||
|
||||
var $navbar = $("#navbar"),
|
||||
$extended = $("#extended");
|
||||
|
||||
$("#table").remove();
|
||||
|
||||
if (settings.viewmodes.length > 1) {
|
||||
if ($.inArray("icons", settings.viewmodes) >= 0) {
|
||||
$("<li id='viewicons' class='view'><a href='#'><img alt='view-icons' /><span class='l10n-icons'>icons</span></a></li>")
|
||||
.find("img").attr("src", image("view-icons")).end()
|
||||
.find("a").click(function (event) {
|
||||
viewmode("icons");
|
||||
event.preventDefault();
|
||||
}).end()
|
||||
.appendTo($navbar);
|
||||
}
|
||||
if ($.inArray("details", settings.viewmodes) >= 0) {
|
||||
$("<li id='viewdetails' class='view'><a href='#'><img alt='view-details' /><span class='l10n-details'>details</span></a></li>")
|
||||
.find("img").attr("src", image("view-details")).end()
|
||||
.find("a").click(function (event) {
|
||||
viewmode("details");
|
||||
event.preventDefault();
|
||||
}).end()
|
||||
.appendTo($navbar);
|
||||
}
|
||||
}
|
||||
|
||||
// status update
|
||||
$extended.find(".entry 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();
|
||||
}
|
||||
);
|
||||
},
|
||||
shiftTree = function (forceVisible, dontAnimate) {
|
||||
|
||||
var $tree = $("#tree"),
|
||||
$extended = $("#extended");
|
||||
|
||||
if ((settings.slideTree && $tree.outerWidth() < $extended.offset().left) || forceVisible) {
|
||||
if (dontAnimate) {
|
||||
$tree.stop().css({ left: 0 });
|
||||
} else {
|
||||
$tree.stop().animate({ left: 0 });
|
||||
}
|
||||
} else {
|
||||
if (dontAnimate) {
|
||||
$tree.stop().css({ left: 18 - $tree.outerWidth() });
|
||||
} else {
|
||||
$tree.stop().animate({ left: 18 - $tree.outerWidth() });
|
||||
}
|
||||
}
|
||||
},
|
||||
initTree = function () {
|
||||
|
||||
$("#tree").hover(
|
||||
function () { shiftTree(true); },
|
||||
function () { shiftTree(); }
|
||||
);
|
||||
$window.resize(function () { shiftTree(); });
|
||||
shiftTree(false, true);
|
||||
},
|
||||
selectLinks = function (href) {
|
||||
|
||||
var elements = [];
|
||||
$("a[href^='/']").each(function () {
|
||||
|
||||
if ($(this).attr("href") === href) {
|
||||
elements.push(this);
|
||||
}
|
||||
});
|
||||
return $(elements);
|
||||
},
|
||||
linkHoverStates = function () {
|
||||
|
||||
if (settings.linkHoverStates) {
|
||||
$("a[href^='/']:not(.linkedHoverStates)").each(function () {
|
||||
|
||||
var $a = $(this).addClass("linkedHoverStates"),
|
||||
href = $a.attr("href");
|
||||
|
||||
$a.hover(
|
||||
function () { selectLinks(href).addClass("hover"); },
|
||||
function () { selectLinks(href).removeClass("hover"); }
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
formatDates = function (dateFormat) {
|
||||
|
||||
if (dateFormat) {
|
||||
currentDateFormat = dateFormat;
|
||||
}
|
||||
|
||||
$("#extended .entry .date").each(function () {
|
||||
|
||||
var $this = $(this),
|
||||
time = $this.data("time"),
|
||||
formattedDate = time ? new Date(time).toString(currentDateFormat) : "";
|
||||
|
||||
$this.text(formattedDate);
|
||||
});
|
||||
},
|
||||
localize = function (langs, lang, useBrowserLang) {
|
||||
|
||||
var storedLang = amplify.store(settings.store.lang),
|
||||
browserLang, selected, key;
|
||||
|
||||
if (langs[storedLang]) {
|
||||
lang = storedLang;
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
if (!langs[lang]) {
|
||||
lang = "en";
|
||||
}
|
||||
|
||||
selected = langs[lang];
|
||||
if (selected) {
|
||||
$.each(selected, function (key, value) {
|
||||
$(".l10n-" + key).text(value);
|
||||
});
|
||||
$(".lang").text(lang);
|
||||
$(".langOption").removeClass("current");
|
||||
$(".langOption." + lang).addClass("current");
|
||||
H5AI.core.hash({lang: lang});
|
||||
}
|
||||
|
||||
formatDates(selected.dateFormat || settings.dateFormat);
|
||||
},
|
||||
initLangSelector = function (langs) {
|
||||
|
||||
var $langOptions = $("#langSelector .langOptions"),
|
||||
sortedLangsKeys = [],
|
||||
$ul;
|
||||
|
||||
$.each(langs, function (lang) {
|
||||
sortedLangsKeys.push(lang);
|
||||
});
|
||||
sortedLangsKeys.sort();
|
||||
|
||||
$ul = $("<ul />");
|
||||
$.each(sortedLangsKeys, function (idx, lang) {
|
||||
$("<li class='langOption' />")
|
||||
.addClass(lang)
|
||||
.text(lang + " - " + langs[lang].lang)
|
||||
.appendTo($ul)
|
||||
.click(function () {
|
||||
amplify.store(settings.store.lang, lang);
|
||||
localize(langs, lang, false);
|
||||
});
|
||||
});
|
||||
$langOptions
|
||||
.append($ul)
|
||||
.scrollpanel();
|
||||
|
||||
$("#langSelector").hover(
|
||||
function () {
|
||||
$langOptions
|
||||
.css("top", "-" + $langOptions.outerHeight() + "px")
|
||||
.stop(true, true)
|
||||
.fadeIn();
|
||||
$langOptions.get(0).updateScrollbar();
|
||||
},
|
||||
function () {
|
||||
$langOptions
|
||||
.stop(true, true)
|
||||
.fadeOut();
|
||||
}
|
||||
);
|
||||
},
|
||||
onIndicatorClick = function (event) {
|
||||
|
||||
var $indicator = $(this),
|
||||
$entry = $indicator.closest(".entry"),
|
||||
updateTreeScrollbar = $("#tree").get(0).updateScrollbar;
|
||||
|
||||
if ($indicator.hasClass("unknown")) {
|
||||
$.get(api(), { "action": "tree", "href": $entry.find("> a").attr("href") }, function (html) {
|
||||
|
||||
var $content = $(html);
|
||||
|
||||
$indicator.removeClass("unknown");
|
||||
if ($content.find("> li").size() === 0) {
|
||||
$indicator.replaceWith($("<span class='blank' />"));
|
||||
} else {
|
||||
$indicator.addClass("open");
|
||||
$entry.find("> .content").replaceWith($content);
|
||||
updateTreeScrollbar();
|
||||
$content.find(".indicator:not(.initiated)")
|
||||
.click(onIndicatorClick)
|
||||
.addClass("initiated");
|
||||
}
|
||||
});
|
||||
} else if ($indicator.hasClass("open")) {
|
||||
$indicator.removeClass("open");
|
||||
updateTreeScrollbar(true);
|
||||
$entry.find("> .content").slideUp(function () {
|
||||
updateTreeScrollbar();
|
||||
});
|
||||
} else {
|
||||
$indicator.addClass("open");
|
||||
updateTreeScrollbar(true);
|
||||
$entry.find("> .content").slideDown(function () {
|
||||
updateTreeScrollbar();
|
||||
});
|
||||
}
|
||||
},
|
||||
initIndicators = function () {
|
||||
|
||||
$("#tree .entry.folder .indicator:not(.initiated)")
|
||||
.click(onIndicatorClick)
|
||||
.addClass("initiated");
|
||||
},
|
||||
getFileType = function (filename) {
|
||||
|
||||
var dotidx = filename.lastIndexOf('.'),
|
||||
ext = dotidx >= 0 ? filename.substr(dotidx) : filename;
|
||||
|
||||
return extToFileType[ext.toLowerCase()] || "unknown";
|
||||
},
|
||||
formatSizes = function () {
|
||||
|
||||
$("#extended .entry .size").each(function () {
|
||||
|
||||
var $this = $(this),
|
||||
bytes = $this.data("bytes"),
|
||||
formattedSize = bytes >= 0 ? H5AI.util.formatSize(bytes) : "";
|
||||
|
||||
$this.text(formattedSize);
|
||||
});
|
||||
},
|
||||
setTotals = function () {
|
||||
|
||||
var $extended = $("#extended");
|
||||
|
||||
$(".folderTotal").text($extended.find(".entry.folder:not(.folder-parent)").length);
|
||||
$(".fileTotal").text($extended.find(".entry.file").length);
|
||||
},
|
||||
init = function () {
|
||||
|
||||
initViews();
|
||||
viewmode();
|
||||
initTopSpace();
|
||||
initTree();
|
||||
linkHoverStates();
|
||||
initLangSelector(config.langs);
|
||||
localize(config.langs, settings.lang, settings.useBrowserLang);
|
||||
formatSizes();
|
||||
setTotals();
|
||||
initIndicators();
|
||||
};
|
||||
|
||||
return {
|
||||
settings: settings,
|
||||
hash: hash,
|
||||
api: api,
|
||||
image: image,
|
||||
icon: icon,
|
||||
shiftTree: shiftTree,
|
||||
linkHoverStates: linkHoverStates,
|
||||
initIndicators: initIndicators,
|
||||
formatDates: formatDates,
|
||||
getFileType: getFileType,
|
||||
init: init
|
||||
};
|
||||
}());
|
||||
|
||||
}(window, jQuery, H5AI, H5AI_CONFIG));
|
@ -1,132 +0,0 @@
|
||||
|
||||
(function (document, $, H5AI) {
|
||||
|
||||
H5AI.extended = (function () {
|
||||
|
||||
var initBreadcrumb = function () {
|
||||
|
||||
var $ul = $("body > nav ul"),
|
||||
pathname = "/",
|
||||
path = H5AI.connector.getPath(pathname),
|
||||
pathnameParts = document.location.pathname.split("/"),
|
||||
lastPart = "",
|
||||
title = document.domain;
|
||||
|
||||
$ul.append(H5AI.html.updateCrumbHtml(path));
|
||||
|
||||
$.each(pathnameParts, function (idx, part) {
|
||||
if (part !== "") {
|
||||
pathname += part + "/";
|
||||
$ul.append(H5AI.html.updateCrumbHtml(H5AI.connector.getPath(pathname)));
|
||||
lastPart = part + " - ";
|
||||
title += " > " + part;
|
||||
}
|
||||
});
|
||||
|
||||
document.title = H5AI.util.checkedDecodeUri(lastPart + title);
|
||||
},
|
||||
initExtendedView = function () {
|
||||
|
||||
var $ul, $li;
|
||||
|
||||
$ul = $("<ul/>");
|
||||
$li = $("<li class='header' />")
|
||||
.appendTo($ul)
|
||||
.append($("<a class='icon'></a>"))
|
||||
.append($("<a class='label' href='#'><span class='l10n-name'></span></a>"))
|
||||
.append($("<a class='date' href='#'><span class='l10n-lastModified'></span></a>"))
|
||||
.append($("<a class='size' href='#'><span class='l10n-size'></span></a>"));
|
||||
|
||||
// entries
|
||||
$("#table td").closest("tr").each(function () {
|
||||
var path = H5AI.connector.getPath(document.location.pathname, this);
|
||||
$ul.append(H5AI.html.updateExtendedHtml(path));
|
||||
});
|
||||
|
||||
$("#extended").append($ul);
|
||||
|
||||
// empty
|
||||
if ($ul.children(".entry:not(.folder-parent)").size() === 0) {
|
||||
$("#extended").append($("<div class='empty l10n-empty'>empty</div>"));
|
||||
}
|
||||
$("#extended").append($("<div class='no-match l10n-noMatch'>no match</div>"));
|
||||
},
|
||||
customize = function () {
|
||||
|
||||
if (H5AI.core.settings.customHeader) {
|
||||
$.ajax({
|
||||
url: H5AI.core.settings.customHeader,
|
||||
dataType: "html",
|
||||
success: function (data) {
|
||||
$("#content > header").append($(data)).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (H5AI.core.settings.customFooter) {
|
||||
$.ajax({
|
||||
url: H5AI.core.settings.customFooter,
|
||||
dataType: "html",
|
||||
success: function (data) {
|
||||
$("#content > footer").prepend($(data)).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
fetchPath = function (pathname, callback) {
|
||||
|
||||
H5AI.connector.fetchStatusAndContent(pathname, false, function (status, content) {
|
||||
|
||||
var path = H5AI.connector.getPath(pathname);
|
||||
|
||||
path.status = status;
|
||||
path.content = content;
|
||||
callback(path);
|
||||
});
|
||||
},
|
||||
fetchTree = function (pathname, callback, childPath) {
|
||||
|
||||
fetchPath(pathname, function (path) {
|
||||
|
||||
var parent = H5AI.util.splitPath(pathname).parent;
|
||||
|
||||
path.treeOpen = true;
|
||||
if (childPath) {
|
||||
path.content[childPath.absHref] = childPath;
|
||||
}
|
||||
if (parent === null) {
|
||||
callback(path);
|
||||
} else {
|
||||
fetchTree(parent, callback, path);
|
||||
}
|
||||
});
|
||||
},
|
||||
populateTree = function () {
|
||||
|
||||
fetchTree(document.location.pathname, function (path) {
|
||||
$("#tree")
|
||||
.append(H5AI.html.updateTreeHtml(path))
|
||||
.scrollpanel()
|
||||
.show();
|
||||
H5AI.core.shiftTree(false, true);
|
||||
H5AI.core.linkHoverStates();
|
||||
setTimeout(function () { $("#tree").get(0).updateScrollbar(); }, 1);
|
||||
});
|
||||
},
|
||||
init = function () {
|
||||
|
||||
initBreadcrumb();
|
||||
initExtendedView();
|
||||
customize();
|
||||
H5AI.connector.updatePaths();
|
||||
if (H5AI.core.settings.showTree) {
|
||||
populateTree();
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
init: init
|
||||
};
|
||||
}());
|
||||
|
||||
}(document, jQuery, H5AI));
|
@ -1,111 +0,0 @@
|
||||
|
||||
(function ($, H5AI) {
|
||||
|
||||
H5AI.finder = (function () {
|
||||
|
||||
var filter = function (re) {
|
||||
|
||||
var match = [],
|
||||
noMatch = [];
|
||||
|
||||
if (re) {
|
||||
$('#extended .entry').each(function () {
|
||||
|
||||
var label = $(this).find('.label').text();
|
||||
|
||||
if (label.match(re)) {
|
||||
match.push(this);
|
||||
} else {
|
||||
noMatch.push(this);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
match = $('#extended .entry');
|
||||
}
|
||||
|
||||
if ($(match).length) {
|
||||
$('#extended .no-match').hide();
|
||||
} else {
|
||||
setTimeout(function () {
|
||||
|
||||
$('#extended .no-match').show();
|
||||
}, 200);
|
||||
}
|
||||
$(match).fadeIn(200);
|
||||
$(noMatch).fadeOut(200);
|
||||
},
|
||||
checkState = function (focus) {
|
||||
|
||||
var $filter = $('#filter'),
|
||||
$input = $filter.find('input'),
|
||||
val = $input.val();
|
||||
|
||||
if (val || focus) {
|
||||
$filter.addClass('current');
|
||||
} else {
|
||||
$filter.removeClass('current');
|
||||
}
|
||||
H5AI.core.hash({filter: val});
|
||||
},
|
||||
parseFilterSequence = function (sequence) {
|
||||
|
||||
if (sequence.substr(0,3) === 're:') {
|
||||
return new RegExp(sequence.substr(3));
|
||||
}
|
||||
|
||||
sequence = $.map($.trim(sequence).split(/\s+/), function (part) {
|
||||
|
||||
return H5AI.util.reEscape(part);
|
||||
}).join('|');
|
||||
return new RegExp(sequence);
|
||||
},
|
||||
init = function () {
|
||||
|
||||
if (H5AI.core.settings.showFilter) {
|
||||
$("<li id='filter'><span class='element'><img alt='filter' /><input type='text' value='' placeholder='filter' /></span></li>")
|
||||
.on('click', function () {
|
||||
|
||||
var $input = $(this).find('input');
|
||||
$input.focus();
|
||||
})
|
||||
.find("img").attr("src", H5AI.core.image("filter")).end()
|
||||
.find("input")
|
||||
.on('focus', function () {
|
||||
|
||||
checkState(true);
|
||||
})
|
||||
.on('blur', function () {
|
||||
|
||||
checkState(false);
|
||||
})
|
||||
.on('keyup', function () {
|
||||
|
||||
var $input = $(this),
|
||||
val = $input.val();
|
||||
|
||||
if (val) {
|
||||
filter(parseFilterSequence(val));
|
||||
} else {
|
||||
filter();
|
||||
}
|
||||
checkState($input.is(':focus'));
|
||||
})
|
||||
.end()
|
||||
.appendTo($("#navbar"));
|
||||
|
||||
var initialFilter = H5AI.core.hash('filter');
|
||||
if (initialFilter) {
|
||||
$('#filter input').val(initialFilter);
|
||||
checkState(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
init: init,
|
||||
filter: filter
|
||||
};
|
||||
}());
|
||||
|
||||
}(jQuery, H5AI));
|
@ -1,264 +0,0 @@
|
||||
|
||||
(function ($, H5AI) {
|
||||
|
||||
H5AI.html = (function () {
|
||||
|
||||
var onClick = function (path, context) {
|
||||
|
||||
},
|
||||
updateCrumbHtml = function (path) {
|
||||
|
||||
var $html, $a;
|
||||
|
||||
if (path.html.$crumb && path.html.$crumb.data("status") === path.status) {
|
||||
return path.html.$crumb;
|
||||
}
|
||||
|
||||
$html = $("<li class='crumb'><a><img alt='>' /><span></span></a></li>")
|
||||
.addClass(path.isFolder ? "folder" : "file");
|
||||
|
||||
if (path.status) {
|
||||
$html.data("status", path.status);
|
||||
}
|
||||
|
||||
$a = $html.find("a")
|
||||
.attr("href", path.absHref)
|
||||
.click(function() { onClick(path, "crumb"); })
|
||||
.find("img").attr("src", H5AI.core.image("crumb")).end()
|
||||
.find("span").text(path.label).end();
|
||||
|
||||
if (path.isDomain) {
|
||||
$html.addClass("domain");
|
||||
$a.find("img").attr("src", H5AI.core.image("home"));
|
||||
}
|
||||
|
||||
if (path.isCurrentFolder) {
|
||||
$html.addClass("current");
|
||||
}
|
||||
|
||||
if (!isNaN(path.status)) {
|
||||
if (path.status === 200) {
|
||||
$a.append($("<img class='hint' src='" + H5AI.core.image("page") + "' alt='not listable' />"));
|
||||
} else {
|
||||
$a.append($("<span class='hint'>(" + path.status + ")</span>"));
|
||||
}
|
||||
}
|
||||
|
||||
if (path.html.$crumb) {
|
||||
path.html.$crumb.replaceWith($html);
|
||||
}
|
||||
path.html.$crumb = $html;
|
||||
|
||||
return $html;
|
||||
},
|
||||
updateExtendedHtml = function (path) {
|
||||
|
||||
var $html, $a, $label,
|
||||
formattedDate = path.date ? path.date.toString(H5AI.core.settings.dateFormat) : "",
|
||||
imgClass = "",
|
||||
icon16 = H5AI.core.icon(path.type),
|
||||
icon48 = H5AI.core.icon(path.type, true);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (H5AI.core.settings.showThumbs === true && $.inArray(path.type, H5AI.core.settings.thumbTypes) >= 0) {
|
||||
imgClass = "class='thumb'";
|
||||
var escapedHref = path.absHref.replace(/'/g, "%27").replace(/"/g, "%22");
|
||||
icon16 = H5AI.core.api() + "?action=thumb&href=" + escapedHref + "&width=16&height=16&mode=square";
|
||||
icon48 = H5AI.core.api() + "?action=thumb&href=" + escapedHref + "&width=96&height=46&mode=rational";
|
||||
}
|
||||
|
||||
$label = $("<span class='label'>" + path.label + "</span>");
|
||||
$a = $("<a />")
|
||||
.attr("href", path.absHref)
|
||||
.click(function() { onClick(path, "extended"); })
|
||||
.appendTo($html)
|
||||
.append($("<span class='icon small'><img " + imgClass + " src='" + icon16 + "' alt='" + path.type + "' /></span>"))
|
||||
.append($("<span class='icon big'><img " + imgClass + " src='" + icon48 + "' alt='" + path.type + "' /></span>"))
|
||||
.append($label)
|
||||
.append($("<span class='date' data-time='" + path.time + "'></span>"))
|
||||
.append($("<span class='size' data-bytes='" + 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.core.settings.setParentFolderLabels) {
|
||||
$label.addClass("l10n-parentDirectory");
|
||||
}
|
||||
$html.addClass("folder-parent");
|
||||
}
|
||||
|
||||
if (!isNaN(path.status)) {
|
||||
if (path.status === 200) {
|
||||
$html.addClass("page");
|
||||
$a.find(".icon.small img").attr("src", H5AI.core.icon("folder-page"));
|
||||
$a.find(".icon.big img").attr("src", H5AI.core.icon("folder-page", true));
|
||||
} else {
|
||||
$html.addClass("error");
|
||||
$label.append($("<span class='hint'> " + path.status + " </span>"));
|
||||
}
|
||||
}
|
||||
|
||||
if (path.html.$extended) {
|
||||
path.html.$extended.replaceWith($html);
|
||||
H5AI.core.formatDates();
|
||||
}
|
||||
path.html.$extended = $html;
|
||||
|
||||
return $html;
|
||||
},
|
||||
updateTreeHtml = function (path) {
|
||||
|
||||
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() { onClick(path, "tree"); })
|
||||
.appendTo($html)
|
||||
.append($("<span class='icon'><img src='" + H5AI.core.icon(path.type) + "' /></span>"))
|
||||
.append($("<span class='label'>" + path.label + "</span>"));
|
||||
|
||||
if (path.isFolder) {
|
||||
// indicator
|
||||
if (path.status === undefined || !path.isEmpty()) {
|
||||
$indicator = $("<span class='indicator initiated'><img src='" + H5AI.core.image("tree") + "' /></span>")
|
||||
.click(function (event) {
|
||||
|
||||
var $entry = $indicator.closest(".entry"); // $html
|
||||
|
||||
if ($indicator.hasClass("unknown")) {
|
||||
H5AI.connector.fetchStatusAndContent(path.absHref, false, function (status, content) {
|
||||
|
||||
path.status = status;
|
||||
path.content = content;
|
||||
path.treeOpen = true;
|
||||
$("#tree").get(0).updateScrollbar(true);
|
||||
updateTreeHtml(path);
|
||||
$("#tree").get(0).updateScrollbar();
|
||||
});
|
||||
} else if ($indicator.hasClass("open")) {
|
||||
path.treeOpen = false;
|
||||
$indicator.removeClass("open");
|
||||
$("#tree").get(0).updateScrollbar(true);
|
||||
$entry.find("> ul.content").slideUp(function() {
|
||||
|
||||
$("#tree").get(0).updateScrollbar();
|
||||
});
|
||||
} else {
|
||||
path.treeOpen = true;
|
||||
$indicator.addClass("open");
|
||||
$("#tree").get(0).updateScrollbar(true);
|
||||
$entry.find("> ul.content").slideDown(function() {
|
||||
|
||||
$("#tree").get(0).updateScrollbar();
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if (path.status === undefined) {
|
||||
$indicator.addClass("unknown");
|
||||
} else if (path.treeOpen) {
|
||||
$indicator.addClass("open");
|
||||
}
|
||||
|
||||
$blank.replaceWith($indicator);
|
||||
}
|
||||
|
||||
// is path the domain?
|
||||
if (path.isDomain) {
|
||||
$html.addClass("domain");
|
||||
$a.find(".icon img").attr("src", H5AI.core.icon("folder-home"));
|
||||
}
|
||||
|
||||
// is path the current folder?
|
||||
if (path.isCurrentFolder) {
|
||||
$html.addClass("current");
|
||||
$a.find(".icon img").attr("src", H5AI.core.icon("folder-open"));
|
||||
}
|
||||
|
||||
// does it have subfolders?
|
||||
if (!path.isEmpty()) {
|
||||
$ul = $("<ul class='content' />").appendTo($html);
|
||||
$.each(path.content, function (idx, entry) {
|
||||
$("<li />").append(updateTreeHtml(entry)).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.core.icon("folder-page"));
|
||||
$a.append($("<span class='hint'><img src='" + H5AI.core.image("page") + "' /></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;
|
||||
},
|
||||
updateHtml = function (path) {
|
||||
|
||||
updateCrumbHtml(path);
|
||||
updateExtendedHtml(path);
|
||||
updateTreeHtml(path);
|
||||
};
|
||||
|
||||
return {
|
||||
updateCrumbHtml: updateCrumbHtml,
|
||||
updateExtendedHtml: updateExtendedHtml,
|
||||
updateTreeHtml: updateTreeHtml,
|
||||
updateHtml: updateHtml
|
||||
};
|
||||
}());
|
||||
|
||||
}(jQuery, H5AI));
|
@ -1,95 +0,0 @@
|
||||
|
||||
(function (document, $, H5AI) {
|
||||
|
||||
H5AI.Path = function (folder, tableRow) {
|
||||
|
||||
var path = {},
|
||||
$tds, $a, date, size, splits;
|
||||
|
||||
// path.parentFolder: undefined
|
||||
// path.label: undefined
|
||||
// path.type: undefined
|
||||
// path.href: undefined
|
||||
// path.time: undefined
|
||||
// path.size: undefined
|
||||
// path.absHref: undefined
|
||||
// path.isFolder: undefined
|
||||
// path.isParentFolder: undefined
|
||||
// path.isCurrentFolder: undefined
|
||||
// path.isDomain: undefined
|
||||
|
||||
path.status = undefined; // undefined, "h5ai" or HTTP response code
|
||||
path.content = undefined; // associative array path.absHref -> path
|
||||
path.html = {
|
||||
$crumb: undefined,
|
||||
$extended: undefined,
|
||||
$tree: undefined
|
||||
};
|
||||
path.treeOpen = false;
|
||||
|
||||
if (!H5AI.util.pathEndsWithSlash(folder)) {
|
||||
folder += "/";
|
||||
}
|
||||
|
||||
if (tableRow) {
|
||||
$tds = $(tableRow).find("td");
|
||||
$a = $tds.eq(1).find("a");
|
||||
date = Date.parse($tds.eq(2).text());
|
||||
size = H5AI.util.parseSize($tds.eq(3).text());
|
||||
|
||||
path.parentFolder = folder;
|
||||
path.label = $a.text();
|
||||
path.type = H5AI.util.pathEndsWithSlash(path.label) ? "folder" : H5AI.core.getFileType(path.label);
|
||||
path.href = $a.attr("href");
|
||||
path.time = date ? date.getTime() : 0;
|
||||
path.size = size;
|
||||
} else {
|
||||
splits = H5AI.util.splitPath(folder);
|
||||
|
||||
path.parentFolder = splits.parent || "";
|
||||
path.label = H5AI.util.checkedDecodeUri(splits.name);
|
||||
if (path.label === "/") {
|
||||
path.label = H5AI.util.checkedDecodeUri(document.domain);
|
||||
}
|
||||
path.type = "folder";
|
||||
path.href = splits.name;
|
||||
path.time = 0;
|
||||
path.size = -1;
|
||||
}
|
||||
|
||||
if (H5AI.util.pathEndsWithSlash(path.label)) {
|
||||
path.label = path.label.slice(0, -1);
|
||||
}
|
||||
|
||||
path.isFolder = (path.type === "folder");
|
||||
path.isParentFolder = (path.label === "Parent Directory");
|
||||
if (path.isParentFolder) {
|
||||
path.isFolder = true;
|
||||
path.type = "folder-parent";
|
||||
}
|
||||
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.core.settings.setParentFolderLabels) {
|
||||
if (path.isDomain) {
|
||||
path.label = H5AI.util.checkedDecodeUri(document.domain);
|
||||
} else {
|
||||
splits = H5AI.util.splitPath(path.parentFolder);
|
||||
path.label = H5AI.util.checkedDecodeUri(splits.parentname);
|
||||
}
|
||||
}
|
||||
|
||||
path.isEmpty = function () {
|
||||
|
||||
return !path.content || $.isEmptyObject(path.content);
|
||||
};
|
||||
path.onClick = function (context) {
|
||||
|
||||
H5AI.core.triggerPathClick(path, context);
|
||||
};
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
}(document, jQuery, H5AI));
|
@ -1,158 +0,0 @@
|
||||
|
||||
(function ($, H5AI) {
|
||||
|
||||
H5AI.sort = (function () {
|
||||
|
||||
var type = function (entry) {
|
||||
|
||||
var $entry = $(entry);
|
||||
|
||||
if ($entry.hasClass("folder-parent")) {
|
||||
return 0;
|
||||
} else if ($entry.hasClass("folder")) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
},
|
||||
cmp = function (entry1, entry2, rev, getVal) {
|
||||
|
||||
var res, val1, val2;
|
||||
|
||||
res = type(entry1) - type(entry2);
|
||||
if (res !== 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
val1 = getVal(entry1);
|
||||
val2 = getVal(entry2);
|
||||
if (val1 < val2) {
|
||||
return rev ? 1 : -1;
|
||||
} else if (val1 > val2) {
|
||||
return rev ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
cmpName = function (entry1, entry2) {
|
||||
|
||||
return cmp(entry1, entry2, false, function (entry) {
|
||||
return $(entry).find(".label").text().toLowerCase();
|
||||
});
|
||||
},
|
||||
cmpTime = function (entry1, entry2) {
|
||||
|
||||
return cmp(entry1, entry2, false, function (entry) {
|
||||
return $(entry).find(".date").data("time");
|
||||
});
|
||||
},
|
||||
cmpSize = function (entry1, entry2) {
|
||||
|
||||
return cmp(entry1, entry2, false, function (entry) {
|
||||
return $(entry).find(".size").data("bytes");
|
||||
});
|
||||
},
|
||||
cmpNameRev = function (entry1, entry2) {
|
||||
|
||||
return cmp(entry1, entry2, true, function (entry) {
|
||||
return $(entry).find(".label").text().toLowerCase();
|
||||
});
|
||||
},
|
||||
cmpTimeRev = function (entry1, entry2) {
|
||||
|
||||
return cmp(entry1, entry2, true, function (entry) {
|
||||
return $(entry).find(".date").data("time");
|
||||
});
|
||||
},
|
||||
cmpSizeRev = function (entry1, entry2) {
|
||||
|
||||
return cmp(entry1, entry2, true, function (entry) {
|
||||
return $(entry).find(".size").data("bytes");
|
||||
});
|
||||
},
|
||||
sort = function (fn) {
|
||||
|
||||
$("#extended .entry").detach().sort(fn).appendTo($("#extended > ul"));
|
||||
},
|
||||
$all, orders,
|
||||
sortBy = function (id) {
|
||||
|
||||
var order = orders[id];
|
||||
|
||||
$all.removeClass("ascending").removeClass("descending");
|
||||
order.head.addClass(order.clas);
|
||||
sort(order.fn);
|
||||
H5AI.core.hash({sort: id});
|
||||
},
|
||||
init = function () {
|
||||
|
||||
var $ascending = $("<img src='" + H5AI.core.image("ascending") + "' class='sort ascending' alt='ascending' />"),
|
||||
$descending = $("<img src='" + H5AI.core.image("descending") + "' class='sort descending' alt='descending' />"),
|
||||
initialOrder = H5AI.core.hash('sort'),
|
||||
$header = $("#extended li.header"),
|
||||
$label = $header.find("a.label"),
|
||||
$date = $header.find("a.date"),
|
||||
$size = $header.find("a.size");
|
||||
|
||||
$all = $header.find("a.label,a.date,a.size");
|
||||
orders = {
|
||||
na: {
|
||||
head: $label,
|
||||
clas: "ascending",
|
||||
fn: cmpName
|
||||
},
|
||||
nd: {
|
||||
head: $label,
|
||||
clas: "descending",
|
||||
fn: cmpNameRev
|
||||
},
|
||||
da: {
|
||||
head: $date,
|
||||
clas: "ascending",
|
||||
fn: cmpTime
|
||||
},
|
||||
dd: {
|
||||
head: $date,
|
||||
clas: "descending",
|
||||
fn: cmpTimeRev
|
||||
},
|
||||
sa: {
|
||||
head: $size,
|
||||
clas: "ascending",
|
||||
fn: cmpSize
|
||||
},
|
||||
sd: {
|
||||
head: $size,
|
||||
clas: "descending",
|
||||
fn: cmpSizeRev
|
||||
}
|
||||
};
|
||||
|
||||
sortBy(initialOrder ? initialOrder : H5AI.core.settings.sortorder);
|
||||
|
||||
$label
|
||||
.append($ascending.clone()).append($descending.clone())
|
||||
.click(function (event) {
|
||||
sortBy("n" + ($label.hasClass("ascending") ? "d" : "a"));
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
$date
|
||||
.prepend($ascending.clone()).prepend($descending.clone())
|
||||
.click(function (event) {
|
||||
sortBy("d" + ($date.hasClass("ascending") ? "d" : "a"));
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
$size
|
||||
.prepend($ascending.clone()).prepend($descending.clone())
|
||||
.click(function (event) {
|
||||
sortBy("s" + ($size.hasClass("ascending") ? "d" : "a"));
|
||||
event.preventDefault();
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
init: init
|
||||
};
|
||||
}());
|
||||
|
||||
}(jQuery, H5AI));
|
@ -1,120 +0,0 @@
|
||||
|
||||
(function ($, H5AI) {
|
||||
|
||||
H5AI.util = (function () {
|
||||
|
||||
var reSplitPath = /^\/([^\/]+\/?)$/,
|
||||
reSplitPath2 = /^(\/(?:.*\/)*?([^\/]+)\/)([^\/]+\/?)$/,
|
||||
splitPath = function (pathname) {
|
||||
|
||||
var match;
|
||||
|
||||
if (pathname === "/") {
|
||||
return {
|
||||
parent: null,
|
||||
parentname: null,
|
||||
name: "/"
|
||||
};
|
||||
}
|
||||
match = reSplitPath2.exec(pathname);
|
||||
if (match) {
|
||||
return {
|
||||
parent: match[1],
|
||||
parentname: match[2],
|
||||
name: match[3]
|
||||
};
|
||||
}
|
||||
match = reSplitPath.exec(pathname);
|
||||
if (match) {
|
||||
return {
|
||||
parent: "/",
|
||||
parentname: "/",
|
||||
name: match[1]
|
||||
};
|
||||
}
|
||||
},
|
||||
rePathEndsWithSlash = /\/$/,
|
||||
pathEndsWithSlash = function (pathname) {
|
||||
|
||||
return rePathEndsWithSlash.test(pathname);
|
||||
},
|
||||
getAbsHref = function (folder, tableRow) {
|
||||
|
||||
var $a, isParentFolder, href;
|
||||
|
||||
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;
|
||||
},
|
||||
kilo = 1000.0,
|
||||
reParseSize = /^\s*([\.\d]+)\s*([kmg]?)b?\s*$/i,
|
||||
parseSize = function (str) {
|
||||
|
||||
var match = reParseSize.exec(str),
|
||||
val, unit;
|
||||
|
||||
if (!match) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
val = parseFloat(match[1]);
|
||||
unit = match[2].toLowerCase();
|
||||
if (unit === "k") {
|
||||
val *= kilo;
|
||||
} else if (unit === "m") {
|
||||
val *= kilo * kilo;
|
||||
} else if (unit === "g") {
|
||||
val *= kilo * kilo * kilo;
|
||||
} else if (unit === "t") {
|
||||
val *= kilo * kilo * kilo * kilo;
|
||||
}
|
||||
return val;
|
||||
},
|
||||
sizeUnits = ["B", "KB", "MB", "GB", "TB"],
|
||||
formatSize = function (size) {
|
||||
|
||||
var th = 1000.0,
|
||||
i = 0,
|
||||
maxI = sizeUnits.length - 1;
|
||||
|
||||
if (isNaN(size)) {
|
||||
return size;
|
||||
}
|
||||
|
||||
while (size >= th && i < maxI) {
|
||||
size /= kilo;
|
||||
i += 1;
|
||||
}
|
||||
return (i <= 1 ? Math.round(size) : size.toFixed(1)).toString() + " " + sizeUnits[i];
|
||||
},
|
||||
checkedDecodeUri = function (uri) {
|
||||
|
||||
try {
|
||||
return decodeURI(uri);
|
||||
} catch (err) {}
|
||||
return uri;
|
||||
},
|
||||
reEscape = function (sequence) {
|
||||
|
||||
return sequence.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||||
};
|
||||
|
||||
return {
|
||||
splitPath: splitPath,
|
||||
pathEndsWithSlash: pathEndsWithSlash,
|
||||
getAbsHref: getAbsHref,
|
||||
parseSize: parseSize,
|
||||
formatSize: formatSize,
|
||||
checkedDecodeUri: checkedDecodeUri,
|
||||
reEscape: reEscape
|
||||
};
|
||||
}());
|
||||
|
||||
}(jQuery, H5AI));
|
@ -1,191 +0,0 @@
|
||||
|
||||
(function ($, H5AI) {
|
||||
|
||||
H5AI.zippedDownload = (function () {
|
||||
|
||||
var x = 0,
|
||||
y = 0,
|
||||
$document = $(document),
|
||||
$selectionRect = $("#selection-rect"),
|
||||
selectedHrefsStr = "",
|
||||
$download, $img, $downloadAuth, $downloadUser, $downloadPassword,
|
||||
|
||||
updateDownloadBtn = function () {
|
||||
|
||||
var $selected = $("#extended a.selected"),
|
||||
$downloadBtn = $("#download");
|
||||
|
||||
selectedHrefsStr = "";
|
||||
if ($selected.length) {
|
||||
$selected.each(function () {
|
||||
|
||||
var href = $(this).attr("href");
|
||||
selectedHrefsStr = selectedHrefsStr ? selectedHrefsStr + ":" + href : href;
|
||||
});
|
||||
$downloadBtn.show();
|
||||
} else {
|
||||
$downloadBtn.hide();
|
||||
$downloadAuth.hide();
|
||||
}
|
||||
},
|
||||
selectionUpdate = function (event) {
|
||||
|
||||
var l = Math.min(x, event.pageX),
|
||||
t = Math.min(y, event.pageY),
|
||||
w = Math.abs(x - event.pageX),
|
||||
h = Math.abs(y - event.pageY),
|
||||
selRect;
|
||||
|
||||
event.preventDefault();
|
||||
$selectionRect.css({left: l, top: t, width: w, height: h});
|
||||
|
||||
selRect = $selectionRect.fracs("rect");
|
||||
$("#extended a").removeClass("selecting").each(function () {
|
||||
|
||||
var $a = $(this),
|
||||
rect = $a.fracs("rect"),
|
||||
inter = selRect.intersection(rect);
|
||||
if (inter && !$a.closest(".entry").hasClass("folder-parent")) {
|
||||
$a.addClass("selecting");
|
||||
}
|
||||
});
|
||||
},
|
||||
selectionEnd = function (event) {
|
||||
|
||||
event.preventDefault();
|
||||
$document.off("mousemove", selectionUpdate);
|
||||
$selectionRect.hide().css({left: 0, top: 0, width: 0, height: 0});
|
||||
$("#extended a.selecting.selected").removeClass("selecting").removeClass("selected");
|
||||
$("#extended a.selecting").removeClass("selecting").addClass("selected");
|
||||
updateDownloadBtn();
|
||||
},
|
||||
selectionStart = function (event) {
|
||||
|
||||
var view = $.fracs.viewport();
|
||||
|
||||
x = event.pageX;
|
||||
y = event.pageY;
|
||||
// only on left button and don't block the scrollbars
|
||||
if (event.button !== 0 || x >= view.right || y >= view.bottom) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
$(':focus').blur();
|
||||
if (!event.ctrlKey) {
|
||||
$("#extended a").removeClass("selected");
|
||||
updateDownloadBtn();
|
||||
}
|
||||
$selectionRect.show().css({left: x, top: y, width: 0, height: 0});
|
||||
|
||||
$document
|
||||
.on("mousemove", selectionUpdate)
|
||||
.one("mouseup", selectionEnd);
|
||||
},
|
||||
noSelection = function (event) {
|
||||
|
||||
event.stopImmediatePropagation();
|
||||
return false;
|
||||
},
|
||||
noSelectionUnlessCtrl = function (event) {
|
||||
|
||||
if (!event.ctrlKey) {
|
||||
noSelection(event);
|
||||
}
|
||||
},
|
||||
failed = function () {
|
||||
|
||||
$download.addClass('failed');
|
||||
setTimeout(function () {
|
||||
$download.removeClass('failed');
|
||||
}, 1000);
|
||||
},
|
||||
handleResponse = function (response) {
|
||||
|
||||
|
||||
$download.removeClass('current');
|
||||
$img.attr('src', H5AI.core.image("download"));
|
||||
|
||||
if (response) {
|
||||
if (response.status === 'ok') {
|
||||
window.location = H5AI.core.api() + '?action=getzip&id=' + response.id;
|
||||
} else {
|
||||
if (response.code === 401) {
|
||||
$downloadAuth
|
||||
.css({
|
||||
left: $download.offset().left,
|
||||
top: $download.offset().top + $download.outerHeight()
|
||||
})
|
||||
.show();
|
||||
$downloadUser.focus();
|
||||
}
|
||||
failed();
|
||||
}
|
||||
} else {
|
||||
failed();
|
||||
}
|
||||
},
|
||||
requestZipping = function (hrefsStr) {
|
||||
|
||||
$download.addClass('current');
|
||||
$img.attr('src', H5AI.core.image("loading.gif", true));
|
||||
$.ajax({
|
||||
url: H5AI.core.api(),
|
||||
data: {
|
||||
action: 'zip',
|
||||
hrefs: selectedHrefsStr
|
||||
},
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
beforeSend: function (xhr) {
|
||||
|
||||
var user = $downloadUser.val(),
|
||||
password = $downloadPassword.val();
|
||||
|
||||
if (user) {
|
||||
xhr.setRequestHeader ('Authorization', 'Basic ' + Base64.encode(user + ':' + password));
|
||||
}
|
||||
},
|
||||
success: function (response) {
|
||||
|
||||
handleResponse(response);
|
||||
},
|
||||
failed: function () {
|
||||
|
||||
handleResponse();
|
||||
}
|
||||
});
|
||||
},
|
||||
init = function () {
|
||||
|
||||
if (H5AI.core.settings.zippedDownload) {
|
||||
$("<li id='download'><a href='#'><img alt='download' /><span class='l10n-download'>download</span></a></li>")
|
||||
.find("img").attr("src", H5AI.core.image("download")).end()
|
||||
.find("a").click(function (event) {
|
||||
|
||||
event.preventDefault();
|
||||
$downloadAuth.hide();
|
||||
requestZipping(selectedHrefsStr);
|
||||
}).end()
|
||||
.appendTo($("#navbar"));
|
||||
$("<div id='download-auth'><input id='download-auth-user' type='text' value='' placeholder='user' /><input id='download-auth-password' type='text' value='' placeholder='password' /></div>")
|
||||
.appendTo($("body"));
|
||||
|
||||
$download = $('#download');
|
||||
$downloadAuth = $('#download-auth');
|
||||
$downloadUser = $('#download-auth-user');
|
||||
$downloadPassword = $('#download-auth-password');
|
||||
$img = $download.find('img');
|
||||
|
||||
$("body>nav,body>footer,#tree,input").on("mousedown", noSelection);
|
||||
$("#content").on("mousedown", "a", noSelectionUnlessCtrl);
|
||||
$document.on("mousedown", selectionStart);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
init: init
|
||||
};
|
||||
}());
|
||||
|
||||
}(jQuery, H5AI));
|
16
src/_h5ai/js/inc/core/entry.js
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
module.define('core/entry', [jQuery, 'core/parser', 'model/entry'], function ($, parser, Entry) {
|
||||
|
||||
var absHref = document.location.pathname;
|
||||
|
||||
parser.parse(absHref, $('body'));
|
||||
$('#data-apache-autoindex').remove();
|
||||
|
||||
var entry = Entry.get(absHref);
|
||||
entry.status = 'h5ai';
|
||||
if (entry.parent) {
|
||||
entry.parent.isParentFolder = true;
|
||||
}
|
||||
|
||||
return entry;
|
||||
});
|
25
src/_h5ai/js/inc/core/event.js
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
module.define('core/event', [amplify], function (amplify) {
|
||||
|
||||
var sub = function (topic, callback) {
|
||||
|
||||
amplify.subscribe(topic, callback);
|
||||
},
|
||||
|
||||
unsub = function (topic, callback) {
|
||||
|
||||
amplify.unsubscribe(topic, callback);
|
||||
},
|
||||
|
||||
pub = function (topic, data) {
|
||||
|
||||
// console.log('EVENT PUB', topic, data);
|
||||
amplify.publish(topic, data);
|
||||
};
|
||||
|
||||
return {
|
||||
sub: sub,
|
||||
unsub: unsub,
|
||||
pub: pub
|
||||
};
|
||||
});
|
80
src/_h5ai/js/inc/core/format.js
Normal file
@ -0,0 +1,80 @@
|
||||
|
||||
module.define('core/format', [moment], function (moment) {
|
||||
|
||||
var reParseSize = /^\s*([\.\d]+)\s*([kmgt]?)b?\s*$/i,
|
||||
treshhold = 1000.0,
|
||||
kilo = 1000.0,
|
||||
sizeUnits = ['B', 'KB', 'MB', 'GB', 'TB'],
|
||||
|
||||
parseSize = function (str) {
|
||||
|
||||
var match = reParseSize.exec(str),
|
||||
val, unit;
|
||||
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
|
||||
val = parseFloat(match[1]);
|
||||
unit = match[2].toLowerCase();
|
||||
if (unit === 'k') {
|
||||
val *= kilo;
|
||||
} else if (unit === 'm') {
|
||||
val *= kilo * kilo;
|
||||
} else if (unit === 'g') {
|
||||
val *= kilo * kilo * kilo;
|
||||
} else if (unit === 't') {
|
||||
val *= kilo * kilo * kilo * kilo;
|
||||
}
|
||||
return val;
|
||||
},
|
||||
|
||||
formatSize = function (size) {
|
||||
|
||||
if (!_.isNumber(size) || size < 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var i = 0,
|
||||
maxI = sizeUnits.length - 1;
|
||||
|
||||
while (size >= treshhold && i < maxI) {
|
||||
size /= kilo;
|
||||
i += 1;
|
||||
}
|
||||
return (i <= 1 ? Math.round(size) : size.toFixed(1)).toString() + ' ' + sizeUnits[i];
|
||||
},
|
||||
|
||||
defaultDateFormat = 'YYYY-MM-DD HH:mm',
|
||||
|
||||
setDefaultDateFormat = function (dateFormat) {
|
||||
|
||||
defaultDateFormat = dateFormat;
|
||||
},
|
||||
|
||||
parseDate = function (str, dateFormat) {
|
||||
|
||||
try { // problems with ie < 9 :(
|
||||
return moment(str, dateFormat || defaultDateFormat).valueOf() || null;
|
||||
} catch (err) {}
|
||||
|
||||
return Date.parse(str).valueOf() || null;
|
||||
},
|
||||
|
||||
formatDate = function (millis, dateFormat) {
|
||||
|
||||
if (!_.isNumber(millis) || !millis) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return moment(millis).format(dateFormat || defaultDateFormat);
|
||||
};
|
||||
|
||||
return {
|
||||
parseSize: parseSize,
|
||||
formatSize: formatSize,
|
||||
setDefaultDateFormat: setDefaultDateFormat,
|
||||
parseDate: parseDate,
|
||||
formatDate: formatDate
|
||||
};
|
||||
});
|
9
src/_h5ai/js/inc/core/parser.js
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
module.define('core/parser', [jQuery], function ($) {
|
||||
|
||||
if ($('#data-generic-json').length) {
|
||||
return module.require('parser/generic-json');
|
||||
}
|
||||
|
||||
return module.require('parser/apache-autoindex');
|
||||
});
|
22
src/_h5ai/js/inc/core/resource.js
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
module.define('core/resource', ['core/settings'], function (settings) {
|
||||
|
||||
var api = function () {
|
||||
|
||||
return settings.h5aiAbsHref + 'php/api.php';
|
||||
},
|
||||
image = function (id, noPngExt) {
|
||||
|
||||
return settings.h5aiAbsHref + 'images/' + id + (noPngExt ? '' : '.png');
|
||||
},
|
||||
icon = function (id, big) {
|
||||
|
||||
return settings.h5aiAbsHref + 'icons/' + (big ? '48x48' : '16x16') + '/' + id + '.png';
|
||||
};
|
||||
|
||||
return {
|
||||
api: api,
|
||||
image: image,
|
||||
icon: icon
|
||||
};
|
||||
});
|
93
src/_h5ai/js/inc/core/settings.js
Normal file
@ -0,0 +1,93 @@
|
||||
|
||||
module.define('core/settings', [H5AI_CONFIG], function (config) {
|
||||
|
||||
var defaults = {
|
||||
rootAbsHref: '/',
|
||||
h5aiAbsHref: '/_h5ai/'
|
||||
};
|
||||
|
||||
return _.extend({}, defaults, config.options);
|
||||
});
|
||||
|
||||
|
||||
module.define('core/types', [H5AI_CONFIG], function (config) {
|
||||
|
||||
var reEndsWithSlash = /\/$/,
|
||||
reStartsWithDot = /^\./,
|
||||
|
||||
fileExts = {},
|
||||
fileNames = {},
|
||||
|
||||
parse = function (types) {
|
||||
|
||||
_.each(types, function (matches, type) {
|
||||
|
||||
_.each(matches, function (match) {
|
||||
|
||||
match = match.toLowerCase();
|
||||
|
||||
if (reStartsWithDot.test(match)) {
|
||||
fileExts[match] = type;
|
||||
} else {
|
||||
fileNames[match] = type;
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
getType = function (sequence) {
|
||||
|
||||
if (reEndsWithSlash.test(sequence)) {
|
||||
return 'folder';
|
||||
}
|
||||
|
||||
sequence = sequence.toLowerCase();
|
||||
|
||||
var slashidx = sequence.lastIndexOf('/'),
|
||||
name = slashidx >= 0 ? sequence.substr(slashidx + 1) : sequence,
|
||||
dotidx = sequence.lastIndexOf('.'),
|
||||
ext = dotidx >= 0 ? sequence.substr(dotidx) : sequence;
|
||||
|
||||
return fileNames[name] || fileExts[ext] || 'unknown';
|
||||
};
|
||||
|
||||
parse(_.extend({}, config.types));
|
||||
|
||||
return {
|
||||
getType: getType
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
module.define('core/langs', [H5AI_CONFIG], function (config) {
|
||||
|
||||
var defaults = {
|
||||
lang: 'unknown',
|
||||
details: 'details',
|
||||
icons: 'icons',
|
||||
name: 'Name',
|
||||
lastModified: 'Last modified',
|
||||
size: 'Size',
|
||||
parentDirectory: 'Parent Directory',
|
||||
empty: 'empty',
|
||||
folders: 'folders',
|
||||
files: 'files',
|
||||
download: 'download',
|
||||
noMatch: 'no match',
|
||||
dateFormat: 'YYYY-MM-DD HH:mm'
|
||||
},
|
||||
|
||||
translations = {},
|
||||
|
||||
parse = function (langs) {
|
||||
|
||||
_.each(langs, function (trans, lang) {
|
||||
|
||||
translations[lang] = _.extend({}, defaults, trans);
|
||||
});
|
||||
};
|
||||
|
||||
parse(_.extend({}, config.langs));
|
||||
|
||||
return translations;
|
||||
});
|
18
src/_h5ai/js/inc/core/store.js
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
module.define('core/store', [amplify], function (amplify) {
|
||||
|
||||
var put = function (key, value) {
|
||||
|
||||
amplify.store(key, value);
|
||||
},
|
||||
|
||||
get = function (key) {
|
||||
|
||||
return amplify.store(key);
|
||||
};
|
||||
|
||||
return {
|
||||
put: put,
|
||||
get: get
|
||||
};
|
||||
});
|
84
src/_h5ai/js/inc/ext/crumb.js
Normal file
@ -0,0 +1,84 @@
|
||||
|
||||
module.define('ext/crumb', [jQuery, 'core/settings', 'core/resource', 'core/entry'], function ($, allsettings, resource, entry) {
|
||||
|
||||
var defaults = {
|
||||
enabled: true
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.crumb),
|
||||
|
||||
template = '<li class="crumb">' +
|
||||
'<a>' +
|
||||
'<img src="' + resource.image('crumb') + '" alt=">" />' +
|
||||
'<span />' +
|
||||
'</a>' +
|
||||
'</li>',
|
||||
pageHintTemplate = '<img class="hint" src="' + resource.image('page') + '" alt="has index page" />',
|
||||
statusHintTemplate = '<span class="hint"></span>',
|
||||
|
||||
// updates the crumb for this single entry
|
||||
update = function (entry) {
|
||||
|
||||
if (entry.$crumb && entry.$crumb.data('status') === entry.status) {
|
||||
return entry.$crumb;
|
||||
}
|
||||
|
||||
var $html = $(template),
|
||||
$a = $html.find('a');
|
||||
|
||||
$html
|
||||
.addClass(entry.isFolder() ? 'folder' : 'file')
|
||||
.data('status', entry.status);
|
||||
|
||||
$a
|
||||
.attr('href', entry.absHref)
|
||||
.find('span').text(entry.label).end();
|
||||
|
||||
if (entry.isDomain()) {
|
||||
$html.addClass('domain');
|
||||
$a.find('img').attr('src', resource.image('home'));
|
||||
}
|
||||
|
||||
if (entry.isCurrentFolder()) {
|
||||
$html.addClass('current');
|
||||
}
|
||||
|
||||
if (_.isNumber(entry.status)) {
|
||||
if (entry.status === 200) {
|
||||
$a.append($(pageHintTemplate));
|
||||
} else {
|
||||
$a.append($(statusHintTemplate).text('(' + entry.status + ')'));
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.$crumb) {
|
||||
entry.$crumb.replaceWith($html);
|
||||
}
|
||||
entry.$crumb = $html;
|
||||
|
||||
return $html;
|
||||
},
|
||||
|
||||
// creates the complete crumb from entry down to the root
|
||||
init = function (entry) {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var crumb = entry.getCrumb(),
|
||||
$ul = $('#navbar');
|
||||
|
||||
_.each(crumb, function (e) {
|
||||
|
||||
$ul.append(update(e));
|
||||
|
||||
e.fetchStatus(function (e) {
|
||||
|
||||
update(e);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
init(entry);
|
||||
});
|
42
src/_h5ai/js/inc/ext/custom.js
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
module.define('ext/custom', [jQuery, 'core/settings'], function ($, allsettings) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false,
|
||||
header: '_h5ai.header.html',
|
||||
footer: '_h5ai.footer.html'
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.custom),
|
||||
|
||||
init = function () {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_.isString(settings.header)) {
|
||||
$.ajax({
|
||||
url: settings.header,
|
||||
dataType: 'html',
|
||||
success: function (data) {
|
||||
|
||||
$('<div id="content-header">' + data + '</div>').prependTo('#content');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (_.isString(settings.footer)) {
|
||||
$.ajax({
|
||||
url: settings.footer,
|
||||
dataType: 'html',
|
||||
success: function (data) {
|
||||
|
||||
$('<div id="content-footer">' + data + '</div>').appendTo('#content');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
137
src/_h5ai/js/inc/ext/download.js
Normal file
@ -0,0 +1,137 @@
|
||||
|
||||
module.define('ext/download', [jQuery, 'core/settings', 'core/resource', 'core/event'], function ($, allsettings, resource, event) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false,
|
||||
execution: 'php',
|
||||
format: 'zip'
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.download),
|
||||
|
||||
formats = ['tar', 'zip'],
|
||||
|
||||
downloadBtnTemplate = '<li id="download">' +
|
||||
'<a href="#">' +
|
||||
'<img src="' + resource.image('download') + '" alt="download" />' +
|
||||
'<span class="l10n-download">download</span>' +
|
||||
'</a>' +
|
||||
'</li>',
|
||||
authTemplate = '<div id="download-auth">' +
|
||||
'<input id="download-auth-user" type="text" value="" placeholder="user" />' +
|
||||
'<input id="download-auth-password" type="text" value="" placeholder="password" />' +
|
||||
'</div>',
|
||||
|
||||
selectedHrefsStr = '',
|
||||
$download, $img, $downloadAuth, $downloadUser, $downloadPassword,
|
||||
|
||||
failed = function () {
|
||||
|
||||
$download.addClass('failed');
|
||||
setTimeout(function () {
|
||||
$download.removeClass('failed');
|
||||
}, 1000);
|
||||
},
|
||||
|
||||
handleResponse = function (response) {
|
||||
|
||||
$download.removeClass('current');
|
||||
$img.attr('src', resource.image('download'));
|
||||
|
||||
if (response) {
|
||||
if (response.code === 0) {
|
||||
setTimeout(function () { // wait here so the img above can be updated in time
|
||||
|
||||
window.location = resource.api() + '?action=getarchive&id=' + response.id + '&as=h5ai-selection.' + settings.format;
|
||||
}, 200);
|
||||
} else {
|
||||
if (response.code === 401) {
|
||||
$downloadAuth
|
||||
.css({
|
||||
left: $download.offset().left,
|
||||
top: $download.offset().top + $download.outerHeight()
|
||||
})
|
||||
.show();
|
||||
$downloadUser.focus();
|
||||
}
|
||||
failed();
|
||||
}
|
||||
} else {
|
||||
failed();
|
||||
}
|
||||
},
|
||||
|
||||
requestArchive = function (hrefsStr) {
|
||||
|
||||
$download.addClass('current');
|
||||
$img.attr('src', resource.image('loading.gif', true));
|
||||
$.ajax({
|
||||
url: resource.api(),
|
||||
data: {
|
||||
action: 'archive',
|
||||
execution: settings.execution,
|
||||
format: settings.format,
|
||||
hrefs: hrefsStr
|
||||
},
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
beforeSend: function (xhr) {
|
||||
|
||||
var user = $downloadUser.val(),
|
||||
password = $downloadPassword.val();
|
||||
|
||||
if (user) {
|
||||
xhr.setRequestHeader('Authorization', 'Basic ' + Base64.encode(user + ':' + password));
|
||||
}
|
||||
},
|
||||
success: function (response) {
|
||||
|
||||
handleResponse(response);
|
||||
},
|
||||
error: function () {
|
||||
|
||||
handleResponse();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onSelection = function (entries) {
|
||||
|
||||
selectedHrefsStr = '';
|
||||
if (entries.length) {
|
||||
selectedHrefsStr = _.map(entries, function (entry) {
|
||||
|
||||
return entry.absHref;
|
||||
}).join(':');
|
||||
$download.appendTo('#navbar').show();
|
||||
} else {
|
||||
$download.hide();
|
||||
$downloadAuth.hide();
|
||||
}
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$download = $(downloadBtnTemplate)
|
||||
.find('a').on('click', function (event) {
|
||||
|
||||
event.preventDefault();
|
||||
$downloadAuth.hide();
|
||||
requestArchive(selectedHrefsStr);
|
||||
}).end()
|
||||
.appendTo('#navbar');
|
||||
$img = $download.find('img');
|
||||
|
||||
$downloadAuth = $(authTemplate).appendTo('body');
|
||||
$downloadUser = $downloadAuth.find('#download-auth-user');
|
||||
$downloadPassword = $downloadAuth.find('#download-auth-password');
|
||||
|
||||
event.sub('selection', onSelection);
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
123
src/_h5ai/js/inc/ext/filter.js
Normal file
@ -0,0 +1,123 @@
|
||||
|
||||
module.define('ext/filter', [jQuery, 'core/settings', 'core/resource'], function ($, allsettings, resource) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.filter),
|
||||
|
||||
template = '<li id="filter">' +
|
||||
'<span class="element">' +
|
||||
'<img src="' + resource.image('filter') + '" alt="filter" />' +
|
||||
'<input type="text" value="" placeholder="filter" />' +
|
||||
'</span>' +
|
||||
'</li>',
|
||||
noMatchTemplate = '<div class="no-match l10n-noMatch">no match</div>',
|
||||
|
||||
$filter, $input, $noMatch,
|
||||
|
||||
filter = function (re) {
|
||||
|
||||
var match = [],
|
||||
noMatch = [],
|
||||
duration = 200;
|
||||
|
||||
if (re) {
|
||||
$('#extended .entry').each(function () {
|
||||
|
||||
var label = $(this).find('.label').text();
|
||||
|
||||
if (label.match(re)) {
|
||||
match.push(this);
|
||||
} else {
|
||||
noMatch.push(this);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
match = $('#extended .entry');
|
||||
}
|
||||
|
||||
if ($(match).length) {
|
||||
$noMatch.hide();
|
||||
} else {
|
||||
setTimeout(function () { $noMatch.show(); }, duration);
|
||||
}
|
||||
$(match).fadeIn(duration);
|
||||
$(noMatch).fadeOut(duration);
|
||||
},
|
||||
|
||||
checkState = function (focus) {
|
||||
|
||||
var val = $input.val();
|
||||
|
||||
if (val || focus) {
|
||||
$filter.addClass('current');
|
||||
} else {
|
||||
$filter.removeClass('current');
|
||||
}
|
||||
},
|
||||
|
||||
escapeRegExp = function (sequence) {
|
||||
|
||||
return sequence.replace(/[\-\[\]{}()*+?.,\\$\^|#\s]/g, '\\$&');
|
||||
// return sequence.replace(/[|()\[{.+*?^$\\]/g,"\\$0");
|
||||
},
|
||||
|
||||
parseFilterSequence = function (sequence) {
|
||||
|
||||
if (sequence.substr(0, 3) === 're:') {
|
||||
return new RegExp(sequence.substr(3));
|
||||
}
|
||||
|
||||
sequence = $.map($.trim(sequence).split(/\s+/), function (part) {
|
||||
|
||||
return escapeRegExp(part);
|
||||
}).join('|');
|
||||
|
||||
return new RegExp(sequence);
|
||||
},
|
||||
|
||||
update = function () {
|
||||
|
||||
var val = $input.val();
|
||||
|
||||
if (val) {
|
||||
filter(parseFilterSequence(val));
|
||||
} else {
|
||||
filter();
|
||||
}
|
||||
checkState($input.is(':focus'));
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$filter = $(template);
|
||||
$input = $filter.find('input');
|
||||
$noMatch = $(noMatchTemplate).appendTo('#extended');
|
||||
|
||||
$filter
|
||||
.on('click', function () {
|
||||
|
||||
$input.focus();
|
||||
})
|
||||
.appendTo('#navbar');
|
||||
|
||||
$input
|
||||
.on('focus', function () {
|
||||
|
||||
checkState(true);
|
||||
})
|
||||
.on('blur', function () {
|
||||
|
||||
checkState(false);
|
||||
})
|
||||
.on('keyup', update);
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
14
src/_h5ai/js/inc/ext/folderstatus.js
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
module.define('ext/folderstatus', [jQuery, 'core/settings'], function ($, allsettings) {
|
||||
|
||||
var defaults = {
|
||||
enabled: true,
|
||||
folders: {}
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.folderstatus),
|
||||
|
||||
folders = settings.enabled ? settings.folders : defaults.folders;
|
||||
|
||||
return folders;
|
||||
});
|
117
src/_h5ai/js/inc/ext/l10n.js
Normal file
@ -0,0 +1,117 @@
|
||||
|
||||
module.define('ext/l10n', [jQuery, 'core/settings', 'core/langs', 'core/format', 'core/store'], function ($, allsettings, langs, format, store) {
|
||||
|
||||
var defaults = {
|
||||
enabled: true,
|
||||
lang: 'en',
|
||||
useBrowserLang: true
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.l10n),
|
||||
|
||||
template = '<span id="langSelector">' +
|
||||
'<span class="lang">en</span> - <span class="l10n-lang">english</span>' +
|
||||
'<span class="langOptions"> <ul /> </span>' +
|
||||
'</span>',
|
||||
langOptionTemplate = '<li class="langOption" />',
|
||||
|
||||
storekey = 'h5ai.language',
|
||||
|
||||
currentLang = null,
|
||||
|
||||
localize = function (langs, lang, useBrowserLang) {
|
||||
|
||||
var storedLang = store.get(storekey),
|
||||
browserLang, key;
|
||||
|
||||
if (langs[storedLang]) {
|
||||
lang = storedLang;
|
||||
} else if (useBrowserLang) {
|
||||
browserLang = navigator.language || navigator.browserLanguage;
|
||||
if (browserLang) {
|
||||
if (langs[browserLang]) {
|
||||
lang = browserLang;
|
||||
} else if (browserLang.length > 2 && langs[browserLang.substr(0, 2)]) {
|
||||
lang = browserLang.substr(0, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!langs[lang]) {
|
||||
lang = 'en';
|
||||
}
|
||||
|
||||
currentLang = langs[lang];
|
||||
if (currentLang) {
|
||||
$.each(currentLang, function (key, value) {
|
||||
$('.l10n-' + key).text(value);
|
||||
});
|
||||
$('.lang').text(lang);
|
||||
$('.langOption').removeClass('current');
|
||||
$('.langOption.' + lang).addClass('current');
|
||||
}
|
||||
|
||||
format.setDefaultDateFormat(currentLang.dateFormat);
|
||||
|
||||
$('#extended .entry .date').each(function () {
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
$this.text(format.formatDate($this.data('time')));
|
||||
});
|
||||
},
|
||||
|
||||
initLangSelector = function (langs) {
|
||||
|
||||
var $langSelector = $(template).appendTo('#bottombar .right'),
|
||||
$langOptions = $langSelector.find('.langOptions'),
|
||||
$ul = $langOptions.find('ul'),
|
||||
sortedLangsKeys = [];
|
||||
|
||||
$.each(langs, function (lang) {
|
||||
sortedLangsKeys.push(lang);
|
||||
});
|
||||
sortedLangsKeys.sort();
|
||||
|
||||
$.each(sortedLangsKeys, function (idx, lang) {
|
||||
$(langOptionTemplate)
|
||||
.addClass(lang)
|
||||
.text(lang + ' - ' + langs[lang].lang)
|
||||
.appendTo($ul)
|
||||
.click(function () {
|
||||
store.put(storekey, lang);
|
||||
localize(langs, lang, false);
|
||||
});
|
||||
});
|
||||
$langOptions
|
||||
.append($ul)
|
||||
.scrollpanel();
|
||||
|
||||
$langSelector.hover(
|
||||
function () {
|
||||
$langOptions
|
||||
.css('top', '-' + $langOptions.outerHeight() + 'px')
|
||||
.stop(true, true)
|
||||
.fadeIn();
|
||||
$langOptions.get(0).updateScrollbar();
|
||||
},
|
||||
function () {
|
||||
$langOptions
|
||||
.stop(true, true)
|
||||
.fadeOut();
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
initLangSelector(langs);
|
||||
localize(langs, settings.lang, settings.useBrowserLang);
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
44
src/_h5ai/js/inc/ext/link-hover-states.js
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
module.define('ext/link-hover-states', [jQuery, 'core/settings'], function ($, allsettings) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings['link-hover-states']),
|
||||
|
||||
selector = "a[href^='/']",
|
||||
|
||||
selectLinks = function (href) {
|
||||
|
||||
return $(_.filter($(selector), function (el) {
|
||||
|
||||
return $(el).attr('href') === href;
|
||||
}));
|
||||
},
|
||||
|
||||
onMouseEnter = function () {
|
||||
|
||||
var href = $(this).attr('href');
|
||||
|
||||
selectLinks(href).addClass('hover');
|
||||
},
|
||||
|
||||
onMouseLeave = function () {
|
||||
|
||||
var href = $(this).attr('href');
|
||||
|
||||
selectLinks(href).removeClass('hover');
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
if (settings.enabled) {
|
||||
$('body')
|
||||
.on('mouseenter', selector, onMouseEnter)
|
||||
.on('mouseleave', selector, onMouseLeave);
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
56
src/_h5ai/js/inc/ext/qrcode.js
Normal file
@ -0,0 +1,56 @@
|
||||
|
||||
module.define('ext/qrcode', [jQuery, 'core/settings', 'core/event'], function ($, allsettings, event) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false,
|
||||
size: 150
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.qrcode),
|
||||
|
||||
template = '<div id="context"><div class="qrcode" /></div>',
|
||||
|
||||
$context, hideTimeoutId,
|
||||
|
||||
update = function (entry) {
|
||||
|
||||
$context.find('.qrcode').empty().qrcode({
|
||||
render: Modernizr.canvas ? 'canvas' : 'div',
|
||||
width: settings.size,
|
||||
height: settings.size,
|
||||
color: '#333',
|
||||
text: 'http://' + document.domain + entry.absHref
|
||||
});
|
||||
},
|
||||
|
||||
onMouseenter = function (entry) {
|
||||
|
||||
if (!entry.isFolder()) {
|
||||
update(entry);
|
||||
clearTimeout(hideTimeoutId);
|
||||
$context.stop(true, true).fadeIn(400);
|
||||
}
|
||||
},
|
||||
|
||||
onMouseleave = function (entry) {
|
||||
|
||||
hideTimeoutId = setTimeout(function () {
|
||||
|
||||
$context.stop(true, true).fadeOut(400);
|
||||
}, 200);
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$context = $(template).appendTo('body');
|
||||
|
||||
event.sub('entry.mouseenter', onMouseenter);
|
||||
event.sub('entry.mouseleave', onMouseleave);
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
123
src/_h5ai/js/inc/ext/select.js
Normal file
@ -0,0 +1,123 @@
|
||||
|
||||
module.define('ext/select', [jQuery, 'core/settings', 'core/event'], function ($, allsettings, event) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.select),
|
||||
|
||||
x = 0, y = 0,
|
||||
l = 0, t = 0, w = 0, h = 0,
|
||||
shrink = 1/3,
|
||||
$document = $(document),
|
||||
$selectionRect = $('<div id="selection-rect"></div>'),
|
||||
|
||||
publish = function () {
|
||||
|
||||
var entries = _.map($('#extended .entry.selected'), function (entryElement) {
|
||||
|
||||
return $(entryElement).data('entry');
|
||||
});
|
||||
|
||||
event.pub('selection', entries);
|
||||
},
|
||||
|
||||
selectionUpdate = function (event) {
|
||||
|
||||
l = Math.min(x, event.pageX);
|
||||
t = Math.min(y, event.pageY);
|
||||
w = Math.abs(x - event.pageX);
|
||||
h = Math.abs(y - event.pageY);
|
||||
|
||||
event.preventDefault();
|
||||
$selectionRect
|
||||
.stop(true, true)
|
||||
.css({left: l, top: t, width: w, height: h});
|
||||
|
||||
var selRect = $selectionRect.fracs('rect');
|
||||
$('#extended .entry').removeClass('selecting').each(function () {
|
||||
|
||||
var $entry = $(this),
|
||||
rect = $entry.find('a').fracs('rect'),
|
||||
inter = selRect.intersection(rect);
|
||||
if (inter && !$entry.hasClass('folder-parent')) {
|
||||
$entry.addClass('selecting');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
selectionEnd = function (event) {
|
||||
|
||||
event.preventDefault();
|
||||
$document.off('mousemove', selectionUpdate);
|
||||
$('#extended .entry.selecting.selected').removeClass('selecting').removeClass('selected');
|
||||
$('#extended .entry.selecting').removeClass('selecting').addClass('selected');
|
||||
publish();
|
||||
|
||||
$selectionRect
|
||||
.stop(true, true)
|
||||
.animate({left: l + w * 0.5 * shrink, top: t + h * 0.5 * shrink, width: w * (1 - shrink), height: h * (1 - shrink), opacity: 0}, 300);
|
||||
},
|
||||
|
||||
selectionStart = function (event) {
|
||||
|
||||
var view = $(document).fracs('viewport');
|
||||
|
||||
x = event.pageX;
|
||||
y = event.pageY;
|
||||
l = x;
|
||||
t = y;
|
||||
w = 0;
|
||||
h = 0;
|
||||
|
||||
// only on left button and don't block the scrollbars
|
||||
if (event.button !== 0 || l >= view.right || t >= view.bottom) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
$(':focus').blur();
|
||||
if (!event.ctrlKey) {
|
||||
$('#extended .entry').removeClass('selected');
|
||||
publish();
|
||||
}
|
||||
$selectionRect
|
||||
.stop(true, true)
|
||||
.css({left: l, top: t, width: w, height: h, opacity: 1})
|
||||
.show();
|
||||
|
||||
$document
|
||||
.on('mousemove', selectionUpdate)
|
||||
.one('mouseup', selectionEnd);
|
||||
},
|
||||
|
||||
noSelection = function (event) {
|
||||
|
||||
event.stopImmediatePropagation();
|
||||
return false;
|
||||
},
|
||||
|
||||
noSelectionUnlessCtrl = function (event) {
|
||||
|
||||
if (!event.ctrlKey) {
|
||||
noSelection(event);
|
||||
}
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$selectionRect.hide().appendTo('body');
|
||||
|
||||
$document
|
||||
.on('mousedown', '.noSelection', noSelection)
|
||||
.on('mousedown', '.noSelectionUnlessCtrl,input,a', noSelectionUnlessCtrl)
|
||||
.on('mousedown', selectionStart);
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
145
src/_h5ai/js/inc/ext/sort.js
Normal file
@ -0,0 +1,145 @@
|
||||
|
||||
module.define('ext/sort', [jQuery, 'core/settings', 'core/resource', 'core/store'], function ($, allsettings, resource, store) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false,
|
||||
order: 'na'
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.sort),
|
||||
|
||||
storekey = 'h5ai.sortorder',
|
||||
|
||||
type = function (entry) {
|
||||
|
||||
var $entry = $(entry);
|
||||
|
||||
if ($entry.hasClass('folder-parent')) {
|
||||
return 0;
|
||||
} else if ($entry.hasClass('folder')) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
},
|
||||
|
||||
cmpFn = function (rev, getVal) {
|
||||
|
||||
return function (entry1, entry2) {
|
||||
|
||||
var res, val1, val2;
|
||||
|
||||
res = type(entry1) - type(entry2);
|
||||
if (res !== 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
val1 = getVal(entry1);
|
||||
val2 = getVal(entry2);
|
||||
if (val1 < val2) {
|
||||
return rev ? 1 : -1;
|
||||
} else if (val1 > val2) {
|
||||
return rev ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
},
|
||||
|
||||
getName = function (entry) {
|
||||
|
||||
return $(entry).find('.label').text().toLowerCase();
|
||||
},
|
||||
getTime = function (entry) {
|
||||
|
||||
return $(entry).find('.date').data('time');
|
||||
},
|
||||
getSize = function (entry) {
|
||||
|
||||
return $(entry).find('.size').data('bytes');
|
||||
},
|
||||
|
||||
$all, orders,
|
||||
|
||||
sortBy = function (id) {
|
||||
|
||||
var order = orders[id];
|
||||
|
||||
store.put(storekey, id);
|
||||
|
||||
$all.removeClass('ascending').removeClass('descending');
|
||||
order.head.addClass(order.clas);
|
||||
$('#extended .entry').detach().sort(order.fn).appendTo('#extended > ul');
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $ascending = $('<img src="' + resource.image('ascending') + '" class="sort ascending" alt="ascending" />'),
|
||||
$descending = $('<img src="' + resource.image('descending') + '" class="sort descending" alt="descending" />'),
|
||||
$header = $('#extended li.header'),
|
||||
$label = $header.find('a.label'),
|
||||
$date = $header.find('a.date'),
|
||||
$size = $header.find('a.size');
|
||||
|
||||
$all = $header.find('a.label,a.date,a.size');
|
||||
orders = {
|
||||
na: {
|
||||
head: $label,
|
||||
clas: 'ascending',
|
||||
fn: cmpFn(false, getName)
|
||||
},
|
||||
nd: {
|
||||
head: $label,
|
||||
clas: 'descending',
|
||||
fn: cmpFn(true, getName)
|
||||
},
|
||||
da: {
|
||||
head: $date,
|
||||
clas: 'ascending',
|
||||
fn: cmpFn(false, getTime)
|
||||
},
|
||||
dd: {
|
||||
head: $date,
|
||||
clas: 'descending',
|
||||
fn: cmpFn(true, getTime)
|
||||
},
|
||||
sa: {
|
||||
head: $size,
|
||||
clas: 'ascending',
|
||||
fn: cmpFn(false, getSize)
|
||||
},
|
||||
sd: {
|
||||
head: $size,
|
||||
clas: 'descending',
|
||||
fn: cmpFn(true, getSize)
|
||||
}
|
||||
};
|
||||
|
||||
sortBy(store.get(storekey) || settings.order);
|
||||
|
||||
$label
|
||||
.append($ascending.clone()).append($descending.clone())
|
||||
.click(function (event) {
|
||||
sortBy('n' + ($label.hasClass('ascending') ? 'd' : 'a'));
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
$date
|
||||
.prepend($ascending.clone()).prepend($descending.clone())
|
||||
.click(function (event) {
|
||||
sortBy('d' + ($date.hasClass('ascending') ? 'd' : 'a'));
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
$size
|
||||
.prepend($ascending.clone()).prepend($descending.clone())
|
||||
.click(function (event) {
|
||||
sortBy('s' + ($size.hasClass('ascending') ? 'd' : 'a'));
|
||||
event.preventDefault();
|
||||
});
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
76
src/_h5ai/js/inc/ext/statusbar.js
Normal file
@ -0,0 +1,76 @@
|
||||
|
||||
module.define('ext/statusbar', [jQuery, 'core/settings', 'core/format', 'core/event', 'core/entry'], function ($, allsettings, format, event, entry) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.statusbar),
|
||||
|
||||
template = '<span class="statusbar">' +
|
||||
'<span class="status default">' +
|
||||
'<span class="folderTotal"></span> <span class="l10n-folders">folders</span>' +
|
||||
'<span class="sep">·</span>' +
|
||||
'<span class="fileTotal"></span> <span class="l10n-files">files</span>' +
|
||||
'</span>' +
|
||||
'<span class="status dynamic"></span>' +
|
||||
'</span>',
|
||||
sepTemplate = '<span class="sep">·</span>',
|
||||
|
||||
$statusDynamic,
|
||||
$statusDefault,
|
||||
|
||||
update = function (html) {
|
||||
|
||||
if (html) {
|
||||
$statusDefault.hide();
|
||||
$statusDynamic.empty().append(html).show();
|
||||
} else {
|
||||
$statusDynamic.empty().hide();
|
||||
$statusDefault.show();
|
||||
}
|
||||
},
|
||||
|
||||
init = function (entry) {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $statusbar = $(template),
|
||||
$folderTotal = $statusbar.find('.folderTotal'),
|
||||
$fileTotal = $statusbar.find('.fileTotal');
|
||||
|
||||
$statusDefault = $statusbar.find('.status.default');
|
||||
$statusDynamic = $statusbar.find('.status.dynamic');
|
||||
|
||||
var stats = entry.getStats();
|
||||
$folderTotal.text(stats.folders);
|
||||
$fileTotal.text(stats.files);
|
||||
|
||||
update();
|
||||
|
||||
event.sub('statusbar', update);
|
||||
$('#bottombar > .center').append($statusbar);
|
||||
|
||||
|
||||
|
||||
event.sub('entry.mouseenter', function (entry) {
|
||||
|
||||
var $span = $('<span/>').append(entry.label).append(sepTemplate).append(format.formatDate(entry.time));
|
||||
|
||||
if (!entry.isFolder()) {
|
||||
$span.append(sepTemplate).append(format.formatSize(entry.size));
|
||||
}
|
||||
|
||||
update($span);
|
||||
});
|
||||
|
||||
event.sub('entry.mouseleave', function (entry) {
|
||||
|
||||
update();
|
||||
});
|
||||
};
|
||||
|
||||
init(entry);
|
||||
});
|
59
src/_h5ai/js/inc/ext/thumbnails.js
Normal file
@ -0,0 +1,59 @@
|
||||
|
||||
module.define('ext/thumbnails', [jQuery, 'core/settings', 'core/resource', 'core/entry'], function ($, allsettings, resource, entry) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false,
|
||||
types: ["bmp", "gif", "ico", "image", "jpg", "png", "tiff"],
|
||||
delay: 1000
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.thumbnails),
|
||||
|
||||
requestThumb = function ($img, data) {
|
||||
|
||||
$.getJSON(resource.api(), data, function (json) {
|
||||
|
||||
if (json.code === 0) {
|
||||
$img.addClass('thumb').attr('src', json.absHref);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
checkEntry = function (entry) {
|
||||
|
||||
if (entry.$extended && $.inArray(entry.type, settings.types) >= 0) {
|
||||
|
||||
var $imgSmall = entry.$extended.find('.icon.small img');
|
||||
var $imgBig = entry.$extended.find('.icon.big img');
|
||||
|
||||
requestThumb($imgSmall, {
|
||||
action: 'getthumbsrc',
|
||||
href: entry.absHref,
|
||||
width: 16,
|
||||
height: 16,
|
||||
mode: 'square'
|
||||
});
|
||||
requestThumb($imgBig, {
|
||||
action: 'getthumbsrc',
|
||||
href: entry.absHref,
|
||||
width: 100,
|
||||
height: 48,
|
||||
mode: 'rational'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
init = function (entry) {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(function () {
|
||||
|
||||
_.each(entry.content, checkEntry);
|
||||
}, settings.delay);
|
||||
};
|
||||
|
||||
init(entry);
|
||||
});
|
27
src/_h5ai/js/inc/ext/title.js
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
module.define('ext/title', [jQuery, 'core/settings', 'core/entry'], function ($, allsettings, entry) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.title),
|
||||
|
||||
init = function (entry) {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var labels = _.pluck(entry.getCrumb(), 'label'),
|
||||
title = labels.join(' > ');
|
||||
|
||||
if (labels.length > 1) {
|
||||
title = labels[labels.length - 1] + ' - ' + title;
|
||||
}
|
||||
|
||||
document.title = title;
|
||||
};
|
||||
|
||||
init(entry);
|
||||
});
|
227
src/_h5ai/js/inc/ext/tree.js
Normal file
@ -0,0 +1,227 @@
|
||||
|
||||
module.define('ext/tree', [jQuery, 'core/settings', 'core/resource', 'core/event', 'core/entry', 'core/parser'], function ($, allsettings, resource, event, entry, parser) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false,
|
||||
slide: true
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.tree),
|
||||
|
||||
template = '<div class="entry">' +
|
||||
'<span class="indicator none">' +
|
||||
'<img src="' + resource.image('tree') + '" />' +
|
||||
'</span>' +
|
||||
'<a>' +
|
||||
'<span class="icon"><img /></span>' +
|
||||
'<span class="label"></span>' +
|
||||
'</a>' +
|
||||
'</span>',
|
||||
statusHintTemplate = '<span class="hint"></span>',
|
||||
|
||||
// updates the tree for this single entry
|
||||
update = function (entry) {
|
||||
|
||||
var $html = $(template),
|
||||
$indicator = $html.find('.indicator'),
|
||||
$a = $html.find('a'),
|
||||
$img = $html.find('.icon img'),
|
||||
$label = $html.find('.label');
|
||||
|
||||
$html
|
||||
.addClass(entry.isFolder() ? 'folder' : 'file')
|
||||
.data('entry', entry)
|
||||
.data('status', entry.status);
|
||||
|
||||
$a.attr('href', entry.absHref);
|
||||
$img.attr('src', resource.icon(entry.type));
|
||||
$label.text(entry.label);
|
||||
|
||||
if (entry.isFolder()) {
|
||||
|
||||
var subfolders = entry.getSubfolders();
|
||||
|
||||
// indicator
|
||||
if (!entry.status || (entry.status === 'h5ai' && !entry.isContentFetched) || subfolders.length) {
|
||||
|
||||
$indicator.removeClass('none');
|
||||
|
||||
if (!entry.status || (entry.status === 'h5ai' && !entry.isContentFetched)) {
|
||||
$indicator.addClass('unknown');
|
||||
} else if (entry.isContentVisible) {
|
||||
$indicator.addClass('open');
|
||||
} else {
|
||||
$indicator.addClass('close');
|
||||
}
|
||||
}
|
||||
|
||||
// is it the domain?
|
||||
if (entry.isDomain()) {
|
||||
$html.addClass('domain');
|
||||
$img.attr('src', resource.icon('folder-home'));
|
||||
}
|
||||
|
||||
// is it the current folder?
|
||||
if (entry.isCurrentFolder()) {
|
||||
$html.addClass('current');
|
||||
$img.attr('src', resource.icon('folder-open'));
|
||||
}
|
||||
|
||||
// does it have subfolders?
|
||||
if (subfolders.length) {
|
||||
var $ul = $('<ul class="content" />').appendTo($html);
|
||||
_.each(subfolders, function (e) {
|
||||
$('<li />').append(update(e)).appendTo($ul);
|
||||
});
|
||||
if (!entry.isContentVisible) {
|
||||
$ul.hide();
|
||||
}
|
||||
}
|
||||
|
||||
// reflect folder status
|
||||
if (_.isNumber(entry.status)) {
|
||||
if (entry.status === 200) {
|
||||
$img.attr('src', resource.icon('folder-page'));
|
||||
} else {
|
||||
$html.addClass('error');
|
||||
$a.append($(statusHintTemplate).text(entry.status));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (entry.$tree) {
|
||||
entry.$tree.replaceWith($html);
|
||||
}
|
||||
entry.$tree = $html;
|
||||
|
||||
return $html;
|
||||
},
|
||||
|
||||
createOnIndicatorClick = function (parser) {
|
||||
|
||||
var $tree = $('#tree'),
|
||||
tree = $tree.get(0),
|
||||
slide = function (entry, $indicator, $content, down) {
|
||||
|
||||
entry.isContentVisible = down;
|
||||
$indicator.removeClass('open close').addClass(down ? 'open' : 'close');
|
||||
tree.updateScrollbar(true);
|
||||
$content[down ? 'slideDown' : 'slideUp'](function () {
|
||||
|
||||
tree.updateScrollbar();
|
||||
});
|
||||
};
|
||||
|
||||
return function () {
|
||||
|
||||
var $indicator = $(this),
|
||||
$entry = $indicator.closest('.entry'),
|
||||
entry = $entry.data('entry'),
|
||||
$content = $entry.find('> ul.content');
|
||||
|
||||
if ($indicator.hasClass('unknown')) {
|
||||
|
||||
entry.fetchContent(parser, function (entry) {
|
||||
|
||||
entry.isContentVisible = false;
|
||||
|
||||
var $entry = update(entry),
|
||||
$indicator = $entry.find('> .indicator'),
|
||||
$content = $entry.find('> ul.content');
|
||||
|
||||
if (!$indicator.hasClass('none')) {
|
||||
slide(entry, $indicator, $content, true);
|
||||
}
|
||||
});
|
||||
|
||||
} else if ($indicator.hasClass('open')) {
|
||||
|
||||
slide(entry, $indicator, $content, false);
|
||||
|
||||
} else if ($indicator.hasClass('close')) {
|
||||
|
||||
slide(entry, $indicator, $content, true);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
shiftTree = function (forceVisible, dontAnimate) {
|
||||
|
||||
var $tree = $("#tree"),
|
||||
$extended = $("#extended"),
|
||||
left = ((settings.slide && $tree.outerWidth() < $extended.offset().left) || forceVisible || !$extended.is(':visible')) ? 0 : 18 - $tree.outerWidth();
|
||||
|
||||
if (dontAnimate) {
|
||||
$tree.stop().css({ left: left });
|
||||
} else {
|
||||
$tree.stop().animate({ left: left });
|
||||
}
|
||||
},
|
||||
|
||||
fetchTree = function (entry, parser, callback) {
|
||||
|
||||
entry.isContentVisible = true;
|
||||
entry.fetchContent(parser, function (entry) {
|
||||
|
||||
if (entry.parent) {
|
||||
fetchTree(entry.parent, parser, callback);
|
||||
} else {
|
||||
callback(entry);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
adjustSpacing = function () {
|
||||
|
||||
var $tree = $('#tree'),
|
||||
tree = $tree[0],
|
||||
winHeight = $(window).height(),
|
||||
navHeight = $('#topbar').outerHeight(),
|
||||
footerHeight = $('#bottombar').outerHeight();
|
||||
|
||||
$tree.css({
|
||||
top: navHeight,
|
||||
height: winHeight - navHeight - footerHeight - 16
|
||||
});
|
||||
|
||||
if (tree.updateScrollbar) {
|
||||
tree.updateScrollbar();
|
||||
}
|
||||
},
|
||||
|
||||
// creates the complete tree from entry down to the root
|
||||
init = function (entry, parser) {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $tree = $('<div id="tree" />').appendTo('body');
|
||||
|
||||
fetchTree(entry, parser, function (root) {
|
||||
|
||||
$tree
|
||||
.append(update(root))
|
||||
.scrollpanel()
|
||||
.show();
|
||||
|
||||
adjustSpacing();
|
||||
shiftTree(false, true);
|
||||
setTimeout(function () { $tree.get(0).updateScrollbar(); }, 1);
|
||||
});
|
||||
|
||||
$tree
|
||||
.on('click', '.indicator', createOnIndicatorClick(parser))
|
||||
.on('mouseenter', function () { shiftTree(true); })
|
||||
.on('mouseleave', function () { shiftTree(); });
|
||||
|
||||
event.sub('ready', adjustSpacing);
|
||||
$(window).on('resize', function () {
|
||||
adjustSpacing();
|
||||
shiftTree();
|
||||
});
|
||||
};
|
||||
|
||||
init(entry, parser);
|
||||
});
|
49
src/_h5ai/js/inc/h5ai-info.js
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
module.define('h5ai-info', [jQuery, 'core/resource'], function ($, resource) {
|
||||
|
||||
var setCheckResult = function (id, result) {
|
||||
|
||||
var $ele = $(id).find('.test-result');
|
||||
|
||||
if (result) {
|
||||
$ele.addClass('test-passed').text('yes');
|
||||
} else {
|
||||
$ele.addClass('test-failed').text('no');
|
||||
}
|
||||
},
|
||||
|
||||
handleChecksResponse = function (response) {
|
||||
|
||||
$('.test').each(function () {
|
||||
|
||||
setCheckResult(this, response && response[$(this).data('id')]);
|
||||
});
|
||||
},
|
||||
|
||||
checks = function () {
|
||||
|
||||
$.ajax({
|
||||
url: resource.api(),
|
||||
data: {
|
||||
action: 'getchecks'
|
||||
},
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
success: function (response) {
|
||||
|
||||
handleChecksResponse(response);
|
||||
},
|
||||
error: function () {
|
||||
|
||||
handleChecksResponse();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
checks();
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
21
src/_h5ai/js/inc/h5ai-main.js
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
module.define('h5ai-main', [jQuery, 'core/event'], function ($, event) {
|
||||
|
||||
|
||||
event.pub('beforeView');
|
||||
|
||||
module.require('view/extended');
|
||||
module.require('view/viewmode');
|
||||
module.require('view/spacing');
|
||||
|
||||
$('#h5ai-reference').append(module.require('core/parser').id === 'apache-autoindex' ? ' (js)' : ' (php)');
|
||||
|
||||
event.pub('beforeExt');
|
||||
|
||||
_.each(module.getIds(/^ext\/.+/), function (id) {
|
||||
|
||||
module.require(id);
|
||||
});
|
||||
|
||||
event.pub('ready');
|
||||
});
|
10
src/_h5ai/js/inc/lib/amplify-1.1.0.min.js
vendored
Normal file
10
src/_h5ai/js/inc/lib/amplify.min.js
vendored
@ -1,104 +0,0 @@
|
||||
/**
|
||||
* Version: 1.0 Alpha-1
|
||||
* Build Date: 13-Nov-2007
|
||||
* Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
|
||||
* License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
|
||||
* Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
|
||||
*/
|
||||
Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
|
||||
Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
|
||||
return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
|
||||
return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}}
|
||||
return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);}
|
||||
if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;}
|
||||
var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);}
|
||||
if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);}
|
||||
if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);}
|
||||
if(x.hour||x.hours){this.addHours(x.hour||x.hours);}
|
||||
if(x.month||x.months){this.addMonths(x.month||x.months);}
|
||||
if(x.year||x.years){this.addYears(x.year||x.years);}
|
||||
if(x.day||x.days){this.addDays(x.day||x.days);}
|
||||
return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");}
|
||||
return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;}
|
||||
if(!x.second&&x.second!==0){x.second=-1;}
|
||||
if(!x.minute&&x.minute!==0){x.minute=-1;}
|
||||
if(!x.hour&&x.hour!==0){x.hour=-1;}
|
||||
if(!x.day&&x.day!==0){x.day=-1;}
|
||||
if(!x.month&&x.month!==0){x.month=-1;}
|
||||
if(!x.year&&x.year!==0){x.year=-1;}
|
||||
if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());}
|
||||
if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());}
|
||||
if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());}
|
||||
if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());}
|
||||
if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());}
|
||||
if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());}
|
||||
if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());}
|
||||
if(x.timezone){this.setTimezone(x.timezone);}
|
||||
if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);}
|
||||
return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;}
|
||||
var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}}
|
||||
return w;};Date.prototype.isDST=function(){console.log('isDST');return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();};
|
||||
Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}
|
||||
return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);}
|
||||
var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}
|
||||
return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);}
|
||||
var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";}
|
||||
return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};
|
||||
(function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}
|
||||
break;}
|
||||
return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}
|
||||
rx.push(r[0]);s=r[1];}
|
||||
return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}
|
||||
return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}
|
||||
throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}
|
||||
return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}
|
||||
if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
|
||||
try{r=(px[i].call(this,s));}catch(e){r=null;}
|
||||
if(r){return r;}}
|
||||
throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
|
||||
try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}
|
||||
rx.push(r[0]);s=r[1];}
|
||||
return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}
|
||||
return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}
|
||||
rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}
|
||||
s=q[1];}
|
||||
if(!r){throw new $P.Exception(s);}
|
||||
if(q){throw new $P.Exception(q[1]);}
|
||||
if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}
|
||||
return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}
|
||||
rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}
|
||||
if(!last&&q[1].length===0){last=true;}
|
||||
if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}
|
||||
p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}
|
||||
if(rx[1].length<best[1].length){best=rx;}
|
||||
if(best[1].length===0){break;}}
|
||||
if(best[0].length===0){return best;}
|
||||
if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}
|
||||
best[1]=q[1];}
|
||||
return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}
|
||||
return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];}
|
||||
if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}
|
||||
var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}}
|
||||
return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}
|
||||
this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}
|
||||
var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}
|
||||
return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}
|
||||
for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}
|
||||
if(this.now){return new Date();}
|
||||
var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}
|
||||
if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}
|
||||
if(!this.unit){this.unit="day";}
|
||||
if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}
|
||||
if(this.unit=="week"){this.unit="day";this.value=this.value*7;}
|
||||
this[this.unit+"s"]=this.value*orient;}
|
||||
return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;}
|
||||
if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();}
|
||||
if(this.month&&!this.day){this.day=1;}
|
||||
return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}
|
||||
fn=_C[keys]=_.any.apply(null,px);}
|
||||
return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}
|
||||
return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}
|
||||
return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
|
||||
try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
|
||||
return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
|
||||
return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
|
4
src/_h5ai/js/inc/lib/jquery-1.7.1.min.js
vendored
Normal file
2
src/_h5ai/js/inc/lib/jquery.fracs-0.11.min.js
vendored
Normal file
4
src/_h5ai/js/inc/lib/jquery.min.js
vendored
84
src/_h5ai/js/inc/lib/jquery.mousewheel-3.0.6.js
Normal file
@ -0,0 +1,84 @@
|
||||
/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
|
||||
* Licensed under the MIT License (LICENSE.txt).
|
||||
*
|
||||
* Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
|
||||
* Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
|
||||
* Thanks to: Seamus Leahy for adding deltaX and deltaY
|
||||
*
|
||||
* Version: 3.0.6
|
||||
*
|
||||
* Requires: 1.2.2+
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
var types = ['DOMMouseScroll', 'mousewheel'];
|
||||
|
||||
if ($.event.fixHooks) {
|
||||
for ( var i=types.length; i; ) {
|
||||
$.event.fixHooks[ types[--i] ] = $.event.mouseHooks;
|
||||
}
|
||||
}
|
||||
|
||||
$.event.special.mousewheel = {
|
||||
setup: function() {
|
||||
if ( this.addEventListener ) {
|
||||
for ( var i=types.length; i; ) {
|
||||
this.addEventListener( types[--i], handler, false );
|
||||
}
|
||||
} else {
|
||||
this.onmousewheel = handler;
|
||||
}
|
||||
},
|
||||
|
||||
teardown: function() {
|
||||
if ( this.removeEventListener ) {
|
||||
for ( var i=types.length; i; ) {
|
||||
this.removeEventListener( types[--i], handler, false );
|
||||
}
|
||||
} else {
|
||||
this.onmousewheel = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.extend({
|
||||
mousewheel: function(fn) {
|
||||
return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
|
||||
},
|
||||
|
||||
unmousewheel: function(fn) {
|
||||
return this.unbind("mousewheel", fn);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function handler(event) {
|
||||
var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0;
|
||||
event = $.event.fix(orgEvent);
|
||||
event.type = "mousewheel";
|
||||
|
||||
// Old school scrollwheel delta
|
||||
if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta/120; }
|
||||
if ( orgEvent.detail ) { delta = -orgEvent.detail/3; }
|
||||
|
||||
// New school multidimensional scroll (touchpads) deltas
|
||||
deltaY = delta;
|
||||
|
||||
// Gecko
|
||||
if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
|
||||
deltaY = 0;
|
||||
deltaX = -1*delta;
|
||||
}
|
||||
|
||||
// Webkit
|
||||
if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY/120; }
|
||||
if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = -1*orgEvent.wheelDeltaX/120; }
|
||||
|
||||
// Add event and delta to the front of the arguments
|
||||
args.unshift(event, delta, deltaX, deltaY);
|
||||
|
||||
return ($.event.dispatch || $.event.handle).apply(this, args);
|
||||
}
|
||||
|
||||
})(jQuery);
|
@ -1,84 +0,0 @@
|
||||
/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
|
||||
* Licensed under the MIT License (LICENSE.txt).
|
||||
*
|
||||
* Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
|
||||
* Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
|
||||
* Thanks to: Seamus Leahy for adding deltaX and deltaY
|
||||
*
|
||||
* Version: 3.0.5
|
||||
*
|
||||
* Requires: 1.2.2+
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
var types = ['DOMMouseScroll', 'mousewheel'];
|
||||
|
||||
if ($.event.fixHooks) {
|
||||
for ( var i=types.length; i; ) {
|
||||
$.event.fixHooks[ types[--i] ] = $.event.mouseHooks;
|
||||
}
|
||||
}
|
||||
|
||||
$.event.special.mousewheel = {
|
||||
setup: function() {
|
||||
if ( this.addEventListener ) {
|
||||
for ( var i=types.length; i; ) {
|
||||
this.addEventListener( types[--i], handler, false );
|
||||
}
|
||||
} else {
|
||||
this.onmousewheel = handler;
|
||||
}
|
||||
},
|
||||
|
||||
teardown: function() {
|
||||
if ( this.removeEventListener ) {
|
||||
for ( var i=types.length; i; ) {
|
||||
this.removeEventListener( types[--i], handler, false );
|
||||
}
|
||||
} else {
|
||||
this.onmousewheel = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.extend({
|
||||
mousewheel: function(fn) {
|
||||
return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
|
||||
},
|
||||
|
||||
unmousewheel: function(fn) {
|
||||
return this.unbind("mousewheel", fn);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function handler(event) {
|
||||
var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0;
|
||||
event = $.event.fix(orgEvent);
|
||||
event.type = "mousewheel";
|
||||
|
||||
// Old school scrollwheel delta
|
||||
if ( event.wheelDelta ) { delta = event.wheelDelta/120; }
|
||||
if ( event.detail ) { delta = -event.detail/3; }
|
||||
|
||||
// New school multidimensional scroll (touchpads) deltas
|
||||
deltaY = delta;
|
||||
|
||||
// Gecko
|
||||
if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
|
||||
deltaY = 0;
|
||||
deltaX = -1*delta;
|
||||
}
|
||||
|
||||
// Webkit
|
||||
if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY/120; }
|
||||
if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = -1*orgEvent.wheelDeltaX/120; }
|
||||
|
||||
// Add event and delta to the front of the arguments
|
||||
args.unshift(event, delta, deltaX, deltaY);
|
||||
|
||||
return ($.event.dispatch || $.event.handle).apply(this, args);
|
||||
}
|
||||
|
||||
})(jQuery);
|
@ -72,14 +72,14 @@
|
||||
};
|
||||
|
||||
$element
|
||||
.mousewheel(function (event, delta) {
|
||||
.on('mousewheel', function (event, delta, deltaX, deltaY) {
|
||||
|
||||
$wrapper.scrollTop($wrapper.scrollTop() - 50 * delta);
|
||||
$wrapper.scrollTop($wrapper.scrollTop() - 50 * deltaY);
|
||||
update();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
})
|
||||
.scroll(update);
|
||||
.on('scroll', update);
|
||||
$element.get(0).updateScrollbar = update;
|
||||
$wrapper
|
||||
.css({
|
||||
|
487
src/_h5ai/js/inc/lib/json2.js
Normal file
@ -0,0 +1,487 @@
|
||||
/*
|
||||
http://www.JSON.org/json2.js
|
||||
2011-10-19
|
||||
|
||||
Public Domain.
|
||||
|
||||
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
||||
|
||||
See http://www.JSON.org/js.html
|
||||
|
||||
|
||||
This code should be minified before deployment.
|
||||
See http://javascript.crockford.com/jsmin.html
|
||||
|
||||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
||||
NOT CONTROL.
|
||||
|
||||
|
||||
This file creates a global JSON object containing two methods: stringify
|
||||
and parse.
|
||||
|
||||
JSON.stringify(value, replacer, space)
|
||||
value any JavaScript value, usually an object or array.
|
||||
|
||||
replacer an optional parameter that determines how object
|
||||
values are stringified for objects. It can be a
|
||||
function or an array of strings.
|
||||
|
||||
space an optional parameter that specifies the indentation
|
||||
of nested structures. If it is omitted, the text will
|
||||
be packed without extra whitespace. If it is a number,
|
||||
it will specify the number of spaces to indent at each
|
||||
level. If it is a string (such as '\t' or ' '),
|
||||
it contains the characters used to indent at each level.
|
||||
|
||||
This method produces a JSON text from a JavaScript value.
|
||||
|
||||
When an object value is found, if the object contains a toJSON
|
||||
method, its toJSON method will be called and the result will be
|
||||
stringified. A toJSON method does not serialize: it returns the
|
||||
value represented by the name/value pair that should be serialized,
|
||||
or undefined if nothing should be serialized. The toJSON method
|
||||
will be passed the key associated with the value, and this will be
|
||||
bound to the value
|
||||
|
||||
For example, this would serialize Dates as ISO strings.
|
||||
|
||||
Date.prototype.toJSON = function (key) {
|
||||
function f(n) {
|
||||
// Format integers to have at least two digits.
|
||||
return n < 10 ? '0' + n : n;
|
||||
}
|
||||
|
||||
return this.getUTCFullYear() + '-' +
|
||||
f(this.getUTCMonth() + 1) + '-' +
|
||||
f(this.getUTCDate()) + 'T' +
|
||||
f(this.getUTCHours()) + ':' +
|
||||
f(this.getUTCMinutes()) + ':' +
|
||||
f(this.getUTCSeconds()) + 'Z';
|
||||
};
|
||||
|
||||
You can provide an optional replacer method. It will be passed the
|
||||
key and value of each member, with this bound to the containing
|
||||
object. The value that is returned from your method will be
|
||||
serialized. If your method returns undefined, then the member will
|
||||
be excluded from the serialization.
|
||||
|
||||
If the replacer parameter is an array of strings, then it will be
|
||||
used to select the members to be serialized. It filters the results
|
||||
such that only members with keys listed in the replacer array are
|
||||
stringified.
|
||||
|
||||
Values that do not have JSON representations, such as undefined or
|
||||
functions, will not be serialized. Such values in objects will be
|
||||
dropped; in arrays they will be replaced with null. You can use
|
||||
a replacer function to replace those with JSON values.
|
||||
JSON.stringify(undefined) returns undefined.
|
||||
|
||||
The optional space parameter produces a stringification of the
|
||||
value that is filled with line breaks and indentation to make it
|
||||
easier to read.
|
||||
|
||||
If the space parameter is a non-empty string, then that string will
|
||||
be used for indentation. If the space parameter is a number, then
|
||||
the indentation will be that many spaces.
|
||||
|
||||
Example:
|
||||
|
||||
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
||||
// text is '["e",{"pluribus":"unum"}]'
|
||||
|
||||
|
||||
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
||||
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
||||
|
||||
text = JSON.stringify([new Date()], function (key, value) {
|
||||
return this[key] instanceof Date ?
|
||||
'Date(' + this[key] + ')' : value;
|
||||
});
|
||||
// text is '["Date(---current time---)"]'
|
||||
|
||||
|
||||
JSON.parse(text, reviver)
|
||||
This method parses a JSON text to produce an object or array.
|
||||
It can throw a SyntaxError exception.
|
||||
|
||||
The optional reviver parameter is a function that can filter and
|
||||
transform the results. It receives each of the keys and values,
|
||||
and its return value is used instead of the original value.
|
||||
If it returns what it received, then the structure is not modified.
|
||||
If it returns undefined then the member is deleted.
|
||||
|
||||
Example:
|
||||
|
||||
// Parse the text. Values that look like ISO date strings will
|
||||
// be converted to Date objects.
|
||||
|
||||
myData = JSON.parse(text, function (key, value) {
|
||||
var a;
|
||||
if (typeof value === 'string') {
|
||||
a =
|
||||
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
||||
if (a) {
|
||||
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
||||
+a[5], +a[6]));
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
||||
var d;
|
||||
if (typeof value === 'string' &&
|
||||
value.slice(0, 5) === 'Date(' &&
|
||||
value.slice(-1) === ')') {
|
||||
d = new Date(value.slice(5, -1));
|
||||
if (d) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
|
||||
This is a reference implementation. You are free to copy, modify, or
|
||||
redistribute.
|
||||
*/
|
||||
|
||||
/*jslint evil: true, regexp: true */
|
||||
|
||||
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
||||
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
||||
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
||||
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
||||
test, toJSON, toString, valueOf
|
||||
*/
|
||||
|
||||
|
||||
// Create a JSON object only if one does not already exist. We create the
|
||||
// methods in a closure to avoid creating global variables.
|
||||
|
||||
var JSON;
|
||||
if (!JSON) {
|
||||
JSON = {};
|
||||
}
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function f(n) {
|
||||
// Format integers to have at least two digits.
|
||||
return n < 10 ? '0' + n : n;
|
||||
}
|
||||
|
||||
if (typeof Date.prototype.toJSON !== 'function') {
|
||||
|
||||
Date.prototype.toJSON = function (key) {
|
||||
|
||||
return isFinite(this.valueOf())
|
||||
? this.getUTCFullYear() + '-' +
|
||||
f(this.getUTCMonth() + 1) + '-' +
|
||||
f(this.getUTCDate()) + 'T' +
|
||||
f(this.getUTCHours()) + ':' +
|
||||
f(this.getUTCMinutes()) + ':' +
|
||||
f(this.getUTCSeconds()) + 'Z'
|
||||
: null;
|
||||
};
|
||||
|
||||
String.prototype.toJSON =
|
||||
Number.prototype.toJSON =
|
||||
Boolean.prototype.toJSON = function (key) {
|
||||
return this.valueOf();
|
||||
};
|
||||
}
|
||||
|
||||
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
gap,
|
||||
indent,
|
||||
meta = { // table of character substitutions
|
||||
'\b': '\\b',
|
||||
'\t': '\\t',
|
||||
'\n': '\\n',
|
||||
'\f': '\\f',
|
||||
'\r': '\\r',
|
||||
'"' : '\\"',
|
||||
'\\': '\\\\'
|
||||
},
|
||||
rep;
|
||||
|
||||
|
||||
function quote(string) {
|
||||
|
||||
// If the string contains no control characters, no quote characters, and no
|
||||
// backslash characters, then we can safely slap some quotes around it.
|
||||
// Otherwise we must also replace the offending characters with safe escape
|
||||
// sequences.
|
||||
|
||||
escapable.lastIndex = 0;
|
||||
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
|
||||
var c = meta[a];
|
||||
return typeof c === 'string'
|
||||
? c
|
||||
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||
}) + '"' : '"' + string + '"';
|
||||
}
|
||||
|
||||
|
||||
function str(key, holder) {
|
||||
|
||||
// Produce a string from holder[key].
|
||||
|
||||
var i, // The loop counter.
|
||||
k, // The member key.
|
||||
v, // The member value.
|
||||
length,
|
||||
mind = gap,
|
||||
partial,
|
||||
value = holder[key];
|
||||
|
||||
// If the value has a toJSON method, call it to obtain a replacement value.
|
||||
|
||||
if (value && typeof value === 'object' &&
|
||||
typeof value.toJSON === 'function') {
|
||||
value = value.toJSON(key);
|
||||
}
|
||||
|
||||
// If we were called with a replacer function, then call the replacer to
|
||||
// obtain a replacement value.
|
||||
|
||||
if (typeof rep === 'function') {
|
||||
value = rep.call(holder, key, value);
|
||||
}
|
||||
|
||||
// What happens next depends on the value's type.
|
||||
|
||||
switch (typeof value) {
|
||||
case 'string':
|
||||
return quote(value);
|
||||
|
||||
case 'number':
|
||||
|
||||
// JSON numbers must be finite. Encode non-finite numbers as null.
|
||||
|
||||
return isFinite(value) ? String(value) : 'null';
|
||||
|
||||
case 'boolean':
|
||||
case 'null':
|
||||
|
||||
// If the value is a boolean or null, convert it to a string. Note:
|
||||
// typeof null does not produce 'null'. The case is included here in
|
||||
// the remote chance that this gets fixed someday.
|
||||
|
||||
return String(value);
|
||||
|
||||
// If the type is 'object', we might be dealing with an object or an array or
|
||||
// null.
|
||||
|
||||
case 'object':
|
||||
|
||||
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
||||
// so watch out for that case.
|
||||
|
||||
if (!value) {
|
||||
return 'null';
|
||||
}
|
||||
|
||||
// Make an array to hold the partial results of stringifying this object value.
|
||||
|
||||
gap += indent;
|
||||
partial = [];
|
||||
|
||||
// Is the value an array?
|
||||
|
||||
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
||||
|
||||
// The value is an array. Stringify every element. Use null as a placeholder
|
||||
// for non-JSON values.
|
||||
|
||||
length = value.length;
|
||||
for (i = 0; i < length; i += 1) {
|
||||
partial[i] = str(i, value) || 'null';
|
||||
}
|
||||
|
||||
// Join all of the elements together, separated with commas, and wrap them in
|
||||
// brackets.
|
||||
|
||||
v = partial.length === 0
|
||||
? '[]'
|
||||
: gap
|
||||
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
|
||||
: '[' + partial.join(',') + ']';
|
||||
gap = mind;
|
||||
return v;
|
||||
}
|
||||
|
||||
// If the replacer is an array, use it to select the members to be stringified.
|
||||
|
||||
if (rep && typeof rep === 'object') {
|
||||
length = rep.length;
|
||||
for (i = 0; i < length; i += 1) {
|
||||
if (typeof rep[i] === 'string') {
|
||||
k = rep[i];
|
||||
v = str(k, value);
|
||||
if (v) {
|
||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// Otherwise, iterate through all of the keys in the object.
|
||||
|
||||
for (k in value) {
|
||||
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
||||
v = str(k, value);
|
||||
if (v) {
|
||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Join all of the member texts together, separated with commas,
|
||||
// and wrap them in braces.
|
||||
|
||||
v = partial.length === 0
|
||||
? '{}'
|
||||
: gap
|
||||
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
|
||||
: '{' + partial.join(',') + '}';
|
||||
gap = mind;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
// If the JSON object does not yet have a stringify method, give it one.
|
||||
|
||||
if (typeof JSON.stringify !== 'function') {
|
||||
JSON.stringify = function (value, replacer, space) {
|
||||
|
||||
// The stringify method takes a value and an optional replacer, and an optional
|
||||
// space parameter, and returns a JSON text. The replacer can be a function
|
||||
// that can replace values, or an array of strings that will select the keys.
|
||||
// A default replacer method can be provided. Use of the space parameter can
|
||||
// produce text that is more easily readable.
|
||||
|
||||
var i;
|
||||
gap = '';
|
||||
indent = '';
|
||||
|
||||
// If the space parameter is a number, make an indent string containing that
|
||||
// many spaces.
|
||||
|
||||
if (typeof space === 'number') {
|
||||
for (i = 0; i < space; i += 1) {
|
||||
indent += ' ';
|
||||
}
|
||||
|
||||
// If the space parameter is a string, it will be used as the indent string.
|
||||
|
||||
} else if (typeof space === 'string') {
|
||||
indent = space;
|
||||
}
|
||||
|
||||
// If there is a replacer, it must be a function or an array.
|
||||
// Otherwise, throw an error.
|
||||
|
||||
rep = replacer;
|
||||
if (replacer && typeof replacer !== 'function' &&
|
||||
(typeof replacer !== 'object' ||
|
||||
typeof replacer.length !== 'number')) {
|
||||
throw new Error('JSON.stringify');
|
||||
}
|
||||
|
||||
// Make a fake root object containing our value under the key of ''.
|
||||
// Return the result of stringifying the value.
|
||||
|
||||
return str('', {'': value});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// If the JSON object does not yet have a parse method, give it one.
|
||||
|
||||
if (typeof JSON.parse !== 'function') {
|
||||
JSON.parse = function (text, reviver) {
|
||||
|
||||
// The parse method takes a text and an optional reviver function, and returns
|
||||
// a JavaScript value if the text is a valid JSON text.
|
||||
|
||||
var j;
|
||||
|
||||
function walk(holder, key) {
|
||||
|
||||
// The walk method is used to recursively walk the resulting structure so
|
||||
// that modifications can be made.
|
||||
|
||||
var k, v, value = holder[key];
|
||||
if (value && typeof value === 'object') {
|
||||
for (k in value) {
|
||||
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
||||
v = walk(value, k);
|
||||
if (v !== undefined) {
|
||||
value[k] = v;
|
||||
} else {
|
||||
delete value[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return reviver.call(holder, key, value);
|
||||
}
|
||||
|
||||
|
||||
// Parsing happens in four stages. In the first stage, we replace certain
|
||||
// Unicode characters with escape sequences. JavaScript handles many characters
|
||||
// incorrectly, either silently deleting them, or treating them as line endings.
|
||||
|
||||
text = String(text);
|
||||
cx.lastIndex = 0;
|
||||
if (cx.test(text)) {
|
||||
text = text.replace(cx, function (a) {
|
||||
return '\\u' +
|
||||
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
||||
});
|
||||
}
|
||||
|
||||
// In the second stage, we run the text against regular expressions that look
|
||||
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
||||
// because they can cause invocation, and '=' because it can cause mutation.
|
||||
// But just to be safe, we want to reject all unexpected forms.
|
||||
|
||||
// We split the second stage into 4 regexp operations in order to work around
|
||||
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
||||
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
||||
// replace all simple value tokens with ']' characters. Third, we delete all
|
||||
// open brackets that follow a colon or comma or that begin the text. Finally,
|
||||
// we look to see that the remaining characters are only whitespace or ']' or
|
||||
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
||||
|
||||
if (/^[\],:{}\s]*$/
|
||||
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
|
||||
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
|
||||
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
||||
|
||||
// In the third stage we use the eval function to compile the text into a
|
||||
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
||||
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
||||
// in parens to eliminate the ambiguity.
|
||||
|
||||
j = eval('(' + text + ')');
|
||||
|
||||
// In the optional fourth stage, we recursively walk the new structure, passing
|
||||
// each name/value pair to a reviver function for possible transformation.
|
||||
|
||||
return typeof reviver === 'function'
|
||||
? walk({'': j}, '')
|
||||
: j;
|
||||
}
|
||||
|
||||
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
||||
|
||||
throw new SyntaxError('JSON.parse');
|
||||
};
|
||||
}
|
||||
}());
|
4
src/_h5ai/js/inc/lib/modernizr-2.5.3.min.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/* Modernizr 2.5.3 (Custom Build) | MIT & BSD
|
||||
* Build: http://www.modernizr.com/download/#-opacity-rgba-canvas-history-audio-video-shiv-cssclasses-prefixes
|
||||
*/
|
||||
;window.Modernizr=function(a,b,c){function v(a){j.cssText=a}function w(a,b){return v(m.join(a+";")+(b||""))}function x(a,b){return typeof a===b}function y(a,b){return!!~(""+a).indexOf(b)}function z(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:x(f,"function")?f.bind(d||b):f}return!1}var d="2.5.3",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m=" -webkit- -moz- -o- -ms- ".split(" "),n={},o={},p={},q=[],r=q.slice,s,t={}.hasOwnProperty,u;!x(t,"undefined")&&!x(t.call,"undefined")?u=function(a,b){return t.call(a,b)}:u=function(a,b){return b in a&&x(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=r.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(r.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(r.call(arguments)))};return e}),n.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},n.history=function(){return!!a.history&&!!history.pushState},n.rgba=function(){return v("background-color:rgba(150,255,150,.5)"),y(j.backgroundColor,"rgba")},n.opacity=function(){return w("opacity:.55"),/^0.55$/.test(j.opacity)},n.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},n.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c};for(var A in n)u(n,A)&&(s=A.toLowerCase(),e[s]=n[A](),q.push((e[s]?"":"no-")+s));return v(""),i=k=null,function(a,b){function g(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function h(){var a=k.elements;return typeof a=="string"?a.split(" "):a}function i(a){var b={},c=a.createElement,e=a.createDocumentFragment,f=e();a.createElement=function(a){var e=(b[a]||(b[a]=c(a))).cloneNode();return k.shivMethods&&e.canHaveChildren&&!d.test(a)?f.appendChild(e):e},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+h().join().replace(/\w+/g,function(a){return b[a]=c(a),f.createElement(a),'c("'+a+'")'})+");return n}")(k,f)}function j(a){var b;return a.documentShived?a:(k.shivCSS&&!e&&(b=!!g(a,"article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio{display:none}canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}mark{background:#FF0;color:#000}")),f||(b=!i(a)),b&&(a.documentShived=b),a)}var c=a.html5||{},d=/^<|^(?:button|form|map|select|textarea)$/i,e,f;(function(){var a=b.createElement("a");a.innerHTML="<xyz></xyz>",e="hidden"in a,f=a.childNodes.length==1||function(){try{b.createElement("a")}catch(a){return!0}var c=b.createDocumentFragment();return typeof c.cloneNode=="undefined"||typeof c.createDocumentFragment=="undefined"||typeof c.createElement=="undefined"}()})();var k={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:j};a.html5=k,j(b)}(this,b),e._version=d,e._prefixes=m,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+q.join(" "):""),e}(this,this.document);
|
196
src/_h5ai/js/inc/lib/module.js
Normal file
@ -0,0 +1,196 @@
|
||||
/*!
|
||||
* module.js
|
||||
* author: Lars Jung
|
||||
* license: MIT
|
||||
*/
|
||||
|
||||
(function (global, name) {
|
||||
'use strict';
|
||||
|
||||
var self = {},
|
||||
previous = global[name],
|
||||
|
||||
noConflict = function () {
|
||||
|
||||
if (global[name] === self) {
|
||||
global[name] = previous;
|
||||
}
|
||||
return self;
|
||||
},
|
||||
|
||||
err = function (message) {
|
||||
|
||||
throw name + ' exception: ' + message;
|
||||
},
|
||||
|
||||
definitions = {},
|
||||
modules = {},
|
||||
|
||||
findDepsUnsafe = function (ids) {
|
||||
|
||||
var self = this;
|
||||
var deps = [];
|
||||
|
||||
if (_.isString(ids)) {
|
||||
|
||||
var def = definitions[ids];
|
||||
if (def) {
|
||||
_.each(def.deps, function (id) {
|
||||
|
||||
deps = deps.concat(findDepsUnsafe(id));
|
||||
});
|
||||
deps.push(def.id);
|
||||
} else {
|
||||
deps.push(ids);
|
||||
}
|
||||
} else if (_.isArray(ids)) {
|
||||
|
||||
_.each(ids, function (id) {
|
||||
|
||||
deps = deps.concat(findDepsUnsafe(id));
|
||||
});
|
||||
}
|
||||
|
||||
return _.uniq(deps);
|
||||
},
|
||||
|
||||
findDeps = function (ids) {
|
||||
|
||||
if (ids) {
|
||||
try {
|
||||
return findDepsUnsafe(ids);
|
||||
} catch (e) {
|
||||
err('cyclic dependencies for ids "' + ids + '"');
|
||||
}
|
||||
} else {
|
||||
var res = {};
|
||||
_.each(definitions, function (def, id) {
|
||||
|
||||
res[id] = findDeps(id);
|
||||
});
|
||||
return res;
|
||||
}
|
||||
},
|
||||
|
||||
log = function (showInvDeps) {
|
||||
|
||||
var allDeps = findDeps(),
|
||||
allInvDeps = {},
|
||||
out = '';
|
||||
|
||||
if (!showInvDeps) {
|
||||
_.each(allDeps, function (deps, id) {
|
||||
|
||||
deps.pop();
|
||||
out += (_.has(modules, id) ? '* ' : ' ') + id + ' -> [ ' + deps.join(', ') + ' ]\n';
|
||||
});
|
||||
} else {
|
||||
_.each(definitions, function (def) {
|
||||
|
||||
var invDeps = [];
|
||||
_.each(allDeps, function (depIds, id) {
|
||||
|
||||
if (_.indexOf(depIds, def.id) >= 0) {
|
||||
invDeps.push(id);
|
||||
}
|
||||
});
|
||||
allInvDeps[def.id] = invDeps;
|
||||
});
|
||||
|
||||
_.each(allInvDeps, function (invDeps, id) {
|
||||
|
||||
invDeps.shift();
|
||||
out += (_.has(modules, id) ? '* ' : ' ') + id + ' <- [ ' + invDeps.join(', ') + ' ]\n';
|
||||
});
|
||||
}
|
||||
|
||||
return out;
|
||||
},
|
||||
|
||||
define = function (id, deps, fn) {
|
||||
|
||||
if (_.isFunction(deps)) {
|
||||
fn = deps;
|
||||
deps = [];
|
||||
}
|
||||
if (!_.isString(id)) {
|
||||
err('id must be a string "' + id + '"');
|
||||
}
|
||||
if (!_.isArray(deps)) {
|
||||
err('dependencies must be an array "' + deps + '"');
|
||||
}
|
||||
if (!_.isFunction(fn)) {
|
||||
err('constructor must be a function "' + fn + '"');
|
||||
}
|
||||
if (definitions[id]) {
|
||||
err('id already defined "' + id + '"');
|
||||
}
|
||||
|
||||
definitions[id] = {
|
||||
id: id,
|
||||
deps: deps,
|
||||
fn: fn
|
||||
};
|
||||
},
|
||||
|
||||
getIds = function (regexp) {
|
||||
|
||||
var ids = _.map(definitions, function (def) {
|
||||
|
||||
return def.id;
|
||||
});
|
||||
|
||||
if (!_.isRegExp(regexp)) {
|
||||
return ids;
|
||||
}
|
||||
|
||||
return _.filter(ids, function (id) {
|
||||
|
||||
return regexp.test(id);
|
||||
});
|
||||
},
|
||||
|
||||
isDefined = function (id) {
|
||||
|
||||
return _.isString(id) ? !!definitions[id] : !!id;
|
||||
},
|
||||
|
||||
require = function (id) {
|
||||
|
||||
if (!_.isString(id)) {
|
||||
return id;
|
||||
}
|
||||
|
||||
if (_.has(modules, id)) {
|
||||
return modules[id];
|
||||
}
|
||||
|
||||
var def = definitions[id];
|
||||
if (!def) {
|
||||
err('id not defined "' + id + '"');
|
||||
}
|
||||
|
||||
var deps = _.map(def.deps, function (depId) {
|
||||
|
||||
return require(depId);
|
||||
});
|
||||
|
||||
var obj = def.fn.apply(this, deps);
|
||||
modules[id] = obj;
|
||||
return obj;
|
||||
};
|
||||
|
||||
if (!_) {
|
||||
err(name + ' depends on underscore');
|
||||
}
|
||||
|
||||
self.noConflict = noConflict;
|
||||
self.log = log;
|
||||
self.define = define;
|
||||
self.require = require;
|
||||
self.getIds = getIds;
|
||||
self.isDefined = isDefined;
|
||||
|
||||
global[name] = self;
|
||||
|
||||
}(this, 'module'));
|
6
src/_h5ai/js/inc/lib/moment-1.5.0.min.js
vendored
Normal file
31
src/_h5ai/js/inc/lib/underscore-1.3.1.min.js
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
// Underscore.js 1.3.1
|
||||
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
||||
// Underscore is freely distributable under the MIT license.
|
||||
// Portions of Underscore are inspired or borrowed from Prototype,
|
||||
// Oliver Steele's Functional, and John Resig's Micro-Templating.
|
||||
// For all details and documentation:
|
||||
// http://documentcloud.github.com/underscore
|
||||
(function(){function q(a,c,d){if(a===c)return a!==0||1/a==1/c;if(a==null||c==null)return a===c;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return false;switch(e){case "[object String]":return a==String(c);case "[object Number]":return a!=+a?c!=+c:a==0?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==
|
||||
c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if(typeof a!="object"||typeof c!="object")return false;for(var f=d.length;f--;)if(d[f]==a)return true;d.push(a);var f=0,g=true;if(e=="[object Array]"){if(f=a.length,g=f==c.length)for(;f--;)if(!(g=f in a==f in c&&q(a[f],c[f],d)))break}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return false;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&q(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,
|
||||
h)&&!f--)break;g=!f}}d.pop();return g}var r=this,G=r._,n={},k=Array.prototype,o=Object.prototype,i=k.slice,H=k.unshift,l=o.toString,I=o.hasOwnProperty,w=k.forEach,x=k.map,y=k.reduce,z=k.reduceRight,A=k.filter,B=k.every,C=k.some,p=k.indexOf,D=k.lastIndexOf,o=Array.isArray,J=Object.keys,s=Function.prototype.bind,b=function(a){return new m(a)};if(typeof exports!=="undefined"){if(typeof module!=="undefined"&&module.exports)exports=module.exports=b;exports._=b}else r._=b;b.VERSION="1.3.1";var j=b.each=
|
||||
b.forEach=function(a,c,d){if(a!=null)if(w&&a.forEach===w)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++){if(e in a&&c.call(d,a[e],e,a)===n)break}else for(e in a)if(b.has(a,e)&&c.call(d,a[e],e,a)===n)break};b.map=b.collect=function(a,c,b){var e=[];if(a==null)return e;if(x&&a.map===x)return a.map(c,b);j(a,function(a,g,h){e[e.length]=c.call(b,a,g,h)});if(a.length===+a.length)e.length=a.length;return e};b.reduce=b.foldl=b.inject=function(a,c,d,e){var f=arguments.length>2;a==
|
||||
null&&(a=[]);if(y&&a.reduce===y)return e&&(c=b.bind(c,e)),f?a.reduce(c,d):a.reduce(c);j(a,function(a,b,i){f?d=c.call(e,d,a,b,i):(d=a,f=true)});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(z&&a.reduceRight===z)return e&&(c=b.bind(c,e)),f?a.reduceRight(c,d):a.reduceRight(c);var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=
|
||||
function(a,c,b){var e;E(a,function(a,g,h){if(c.call(b,a,g,h))return e=a,true});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(A&&a.filter===A)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(B&&a.every===B)return a.every(c,b);j(a,function(a,g,h){if(!(e=
|
||||
e&&c.call(b,a,g,h)))return n});return e};var E=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(C&&a.some===C)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return n});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;return p&&a.indexOf===p?a.indexOf(c)!=-1:b=E(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=
|
||||
function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b<e.computed&&(e={value:a,computed:b})});
|
||||
return e.value};b.shuffle=function(a){var b=[],d;j(a,function(a,f){f==0?b[0]=a:(d=Math.floor(Math.random()*(f+1)),b[f]=b[d],b[d]=a)});return b};b.sortBy=function(a,c,d){return b.pluck(b.map(a,function(a,b,g){return{value:a,criteria:c.call(d,a,b,g)}}).sort(function(a,b){var c=a.criteria,d=b.criteria;return c<d?-1:c>d?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,
|
||||
c,d){d||(d=b.identity);for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?e=g+1:f=g}return e};b.toArray=function(a){return!a?[]:a.toArray?a.toArray():b.isArray(a)?i.call(a):b.isArguments(a)?i.call(a):b.values(a)};b.size=function(a){return b.toArray(a).length};b.first=b.head=function(a,b,d){return b!=null&&!d?i.call(a,0,b):a[0]};b.initial=function(a,b,d){return i.call(a,0,a.length-(b==null||d?1:b))};b.last=function(a,b,d){return b!=null&&!d?i.call(a,Math.max(a.length-b,0)):a[a.length-1]};b.rest=
|
||||
b.tail=function(a,b,d){return i.call(a,b==null||d?1:b)};b.compact=function(a){return b.filter(a,function(a){return!!a})};b.flatten=function(a,c){return b.reduce(a,function(a,e){if(b.isArray(e))return a.concat(c?e:b.flatten(e));a[a.length]=e;return a},[])};b.without=function(a){return b.difference(a,i.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a,e=[];b.reduce(d,function(d,g,h){if(0==h||(c===true?b.last(d)!=g:!b.include(d,g)))d[d.length]=g,e[e.length]=a[h];return d},[]);
|
||||
return e};b.union=function(){return b.uniq(b.flatten(arguments,true))};b.intersection=b.intersect=function(a){var c=i.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1));return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.indexOf=function(a,c,
|
||||
d){if(a==null)return-1;var e;if(d)return d=b.sortedIndex(a,c),a[d]===c?d:-1;if(p&&a.indexOf===p)return a.indexOf(c);for(d=0,e=a.length;d<e;d++)if(d in a&&a[d]===c)return d;return-1};b.lastIndexOf=function(a,b){if(a==null)return-1;if(D&&a.lastIndexOf===D)return a.lastIndexOf(b);for(var d=a.length;d--;)if(d in a&&a[d]===b)return d;return-1};b.range=function(a,b,d){arguments.length<=1&&(b=a||0,a=0);for(var d=arguments[2]||1,e=Math.max(Math.ceil((b-a)/d),0),f=0,g=Array(e);f<e;)g[f++]=a,a+=d;return g};
|
||||
var F=function(){};b.bind=function(a,c){var d,e;if(a.bind===s&&s)return s.apply(a,i.call(arguments,1));if(!b.isFunction(a))throw new TypeError;e=i.call(arguments,2);return d=function(){if(!(this instanceof d))return a.apply(c,e.concat(i.call(arguments)));F.prototype=a.prototype;var b=new F,g=a.apply(b,e.concat(i.call(arguments)));return Object(g)===g?g:b}};b.bindAll=function(a){var c=i.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,
|
||||
c){var d={};c||(c=b.identity);return function(){var e=c.apply(this,arguments);return b.has(d,e)?d[e]:d[e]=a.apply(this,arguments)}};b.delay=function(a,b){var d=i.call(arguments,2);return setTimeout(function(){return a.apply(a,d)},b)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(i.call(arguments,1)))};b.throttle=function(a,c){var d,e,f,g,h,i=b.debounce(function(){h=g=false},c);return function(){d=this;e=arguments;var b;f||(f=setTimeout(function(){f=null;h&&a.apply(d,e);i()},c));g?h=true:
|
||||
a.apply(d,e);i();g=true}};b.debounce=function(a,b){var d;return function(){var e=this,f=arguments;clearTimeout(d);d=setTimeout(function(){d=null;a.apply(e,f)},b)}};b.once=function(a){var b=false,d;return function(){if(b)return d;b=true;return d=a.apply(this,arguments)}};b.wrap=function(a,b){return function(){var d=[a].concat(i.call(arguments,0));return b.apply(this,d)}};b.compose=function(){var a=arguments;return function(){for(var b=arguments,d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};
|
||||
b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=J||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.defaults=function(a){j(i.call(arguments,
|
||||
1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return q(a,b,[])};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=o||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};
|
||||
b.isArguments=function(a){return l.call(a)=="[object Arguments]"};if(!b.isArguments(arguments))b.isArguments=function(a){return!(!a||!b.has(a,"callee"))};b.isFunction=function(a){return l.call(a)=="[object Function]"};b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};
|
||||
b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,b){return I.call(a,b)};b.noConflict=function(){r._=G;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.escape=function(a){return(""+a).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")};b.mixin=function(a){j(b.functions(a),
|
||||
function(c){K(c,b[c]=a[c])})};var L=0;b.uniqueId=function(a){var b=L++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var t=/.^/,u=function(a){return a.replace(/\\\\/g,"\\").replace(/\\'/g,"'")};b.template=function(a,c){var d=b.templateSettings,d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.escape||t,function(a,b){return"',_.escape("+
|
||||
u(b)+"),'"}).replace(d.interpolate||t,function(a,b){return"',"+u(b)+",'"}).replace(d.evaluate||t,function(a,b){return"');"+u(b).replace(/[\r\n\t]/g," ")+";__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');",e=new Function("obj","_",d);return c?e(c,b):function(a){return e.call(this,a,b)}};b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var v=function(a,c){return c?b(a).chain():a},K=function(a,c){m.prototype[a]=
|
||||
function(){var a=i.call(arguments);H.call(a,this._wrapped);return v(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return v(d,this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return v(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=
|
||||
true;return this};m.prototype.value=function(){return this._wrapped}}).call(this);
|
@ -1,42 +1,48 @@
|
||||
|
||||
(function ($) {
|
||||
'use strict';
|
||||
/*jslint browser: true, confusion: true, regexp: true, vars: true, white: true */
|
||||
/*global Modernizr, jQuery, amplify, H5AI_CONFIG */
|
||||
'use strict';
|
||||
/*jshint browser: true */
|
||||
/*global _, amplify, Base64, H5AI_CONFIG, jQuery, Modernizr, module, moment */
|
||||
|
||||
var H5AI = {};
|
||||
// @include "core/entry.js"
|
||||
// @include "core/event.js"
|
||||
// @include "core/format.js"
|
||||
// @include "core/parser.js"
|
||||
// @include "core/resource.js"
|
||||
// @include "core/settings.js"
|
||||
// @include "core/store.js"
|
||||
|
||||
// @include "Util.js"
|
||||
// @include "Core.js"
|
||||
// @include "Sort.js"
|
||||
// @include "ZippedDownload.js"
|
||||
// @include "Finder.js"
|
||||
// @include "Context.js"
|
||||
// @include "model/entry.js"
|
||||
|
||||
// @include "parser/apache-autoindex.js"
|
||||
// @include "parser/generic-json.js"
|
||||
|
||||
// @include "view/extended.js"
|
||||
// @include "view/spacing.js"
|
||||
// @include "view/viewmode.js"
|
||||
|
||||
// @include "ext/crumb.js"
|
||||
// @include "ext/custom.js"
|
||||
// @include "ext/download.js"
|
||||
// @include "ext/filter.js"
|
||||
// @include "ext/folderstatus.js"
|
||||
// @include "ext/l10n.js"
|
||||
// @include "ext/link-hover-states.js"
|
||||
// @include "ext/qrcode.js"
|
||||
// @include "ext/select.js"
|
||||
// @include "ext/sort.js"
|
||||
// @include "ext/statusbar.js"
|
||||
// @include "ext/thumbnails.js"
|
||||
// @include "ext/title.js"
|
||||
// @include "ext/tree.js"
|
||||
|
||||
// @include "h5ai-info.js"
|
||||
// @include "h5ai-main.js"
|
||||
|
||||
// @include "Path.js"
|
||||
// @include "Connector.js"
|
||||
// @include "Html.js"
|
||||
// @include "Extended.js"
|
||||
|
||||
$(function () {
|
||||
|
||||
var isPhp = $('html.h5ai-php').length > 0;
|
||||
|
||||
if (!isPhp) {
|
||||
H5AI.extended.init();
|
||||
}
|
||||
|
||||
H5AI.core.init();
|
||||
H5AI.sort.init();
|
||||
H5AI.finder.init();
|
||||
H5AI.zippedDownload.init();
|
||||
H5AI.context.init();
|
||||
|
||||
if (isPhp) {
|
||||
$('#tree').scrollpanel();
|
||||
H5AI.core.shiftTree(false, true);
|
||||
}
|
||||
|
||||
module.require($('body').attr('id'));
|
||||
});
|
||||
|
||||
}(jQuery));
|
||||
|
255
src/_h5ai/js/inc/model/entry.js
Normal file
@ -0,0 +1,255 @@
|
||||
|
||||
module.define('model/entry', [jQuery, 'core/types'], function ($, types) {
|
||||
|
||||
var domain = document.domain,
|
||||
location = document.location.pathname,
|
||||
|
||||
|
||||
// utils
|
||||
|
||||
reEndsWithSlash = /\/$/,
|
||||
|
||||
|
||||
createLabel = function (sequence) {
|
||||
|
||||
if (sequence.length > 1 && reEndsWithSlash.test(sequence)) {
|
||||
sequence = sequence.slice(0, -1);
|
||||
}
|
||||
try {
|
||||
sequence = decodeURI(sequence);
|
||||
} catch (err) {}
|
||||
return sequence;
|
||||
},
|
||||
|
||||
|
||||
reSplitPath = /^\/([^\/]+\/?)$/,
|
||||
reSplitPath2 = /^(\/(?:.*\/)*?([^\/]+)\/)([^\/]+\/?)$/,
|
||||
|
||||
splitPath = function (sequence) {
|
||||
|
||||
var match;
|
||||
|
||||
sequence = sequence.replace(/\/+/g, '/');
|
||||
if (sequence === '/') {
|
||||
return {
|
||||
parent: null,
|
||||
parentname: null,
|
||||
name: '/'
|
||||
};
|
||||
}
|
||||
match = reSplitPath2.exec(sequence);
|
||||
if (match) {
|
||||
return {
|
||||
parent: match[1],
|
||||
parentname: match[2],
|
||||
name: match[3]
|
||||
};
|
||||
}
|
||||
match = reSplitPath.exec(sequence);
|
||||
if (match) {
|
||||
return {
|
||||
parent: '/',
|
||||
parentname: '/',
|
||||
name: match[1]
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
reContentType = /^text\/html;h5ai=/,
|
||||
|
||||
ajaxRequest = function (self, parser, callback) {
|
||||
|
||||
$.ajax({
|
||||
url: self.absHref,
|
||||
type: parser ? 'GET' : 'HEAD',
|
||||
complete: function (xhr) {
|
||||
|
||||
if (xhr.status === 200 && reContentType.test(xhr.getResponseHeader('Content-Type'))) {
|
||||
self.status = 'h5ai';
|
||||
if (parser) {
|
||||
parser.parse(self.absHref, xhr.responseText);
|
||||
}
|
||||
} else {
|
||||
self.status = xhr.status;
|
||||
}
|
||||
|
||||
callback(self);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
// Entry
|
||||
|
||||
cache = {},
|
||||
|
||||
Entry = function (absHref) {
|
||||
|
||||
var split = splitPath(absHref);
|
||||
|
||||
cache[absHref] = this;
|
||||
|
||||
this.absHref = absHref;
|
||||
this.type = types.getType(absHref);
|
||||
this.label = createLabel(absHref === '/' ? domain : split.name);
|
||||
this.time = null;
|
||||
this.size = null;
|
||||
this.parent = null;
|
||||
this.status = null;
|
||||
this.content = {};
|
||||
|
||||
if (split.parent) {
|
||||
this.parent = cache[split.parent] || new Entry(split.parent);
|
||||
this.parent.content[this.absHref] = this;
|
||||
}
|
||||
},
|
||||
|
||||
get = function (absHref, time, size, status) {
|
||||
|
||||
absHref = absHref || location;
|
||||
|
||||
var self = cache[absHref] || new Entry(absHref);
|
||||
|
||||
if (_.isNumber(time)) {
|
||||
self.time = time;
|
||||
}
|
||||
if (_.isNumber(size)) {
|
||||
self.size = size;
|
||||
}
|
||||
if (status) {
|
||||
self.status = status;
|
||||
}
|
||||
|
||||
return self;
|
||||
},
|
||||
|
||||
folderstatus = module.isDefined('ext/folderstatus') ? module.require('ext/folderstatus') : {},
|
||||
|
||||
fetchStatus = function (absHref, callback) {
|
||||
|
||||
var self = cache[absHref] || new Entry(absHref);
|
||||
|
||||
if (self.status || !self.isFolder()) {
|
||||
callback(self);
|
||||
} else if (folderstatus[absHref]) {
|
||||
self.status = folderstatus[absHref];
|
||||
callback(self);
|
||||
} else {
|
||||
ajaxRequest(self, null, callback);
|
||||
}
|
||||
},
|
||||
|
||||
fetchContent = function (absHref, parser, callback) {
|
||||
|
||||
var self = cache[absHref] || new Entry(absHref);
|
||||
|
||||
if (self.isContentFetched || _.keys(self.content).length > 1) {
|
||||
self.isContentFetched = true;
|
||||
callback(self);
|
||||
} else {
|
||||
fetchStatus(absHref, function (self) {
|
||||
|
||||
self.isContentFetched = true;
|
||||
if (self.status === 'h5ai') {
|
||||
ajaxRequest(self, parser, callback);
|
||||
} else {
|
||||
callback(self);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
_.extend(Entry.prototype, {
|
||||
|
||||
isFolder: function () {
|
||||
|
||||
return reEndsWithSlash.test(this.absHref);
|
||||
},
|
||||
|
||||
isCurrentFolder: function () {
|
||||
|
||||
return this.absHref === location;
|
||||
},
|
||||
|
||||
isDomain: function () {
|
||||
|
||||
return this.absHref === '/';
|
||||
},
|
||||
|
||||
isEmpty: function () {
|
||||
|
||||
return _.keys(this.content).length === 0;
|
||||
},
|
||||
|
||||
fetchStatus: function (callback) {
|
||||
|
||||
return fetchStatus(this.absHref, callback);
|
||||
},
|
||||
|
||||
fetchContent: function (parser, callback) {
|
||||
|
||||
return fetchContent(this.absHref, parser, callback);
|
||||
},
|
||||
|
||||
getCrumb: function () {
|
||||
|
||||
var entry = this,
|
||||
crumb = [entry];
|
||||
|
||||
while (entry.parent) {
|
||||
entry = entry.parent;
|
||||
crumb.unshift(entry);
|
||||
}
|
||||
|
||||
return crumb;
|
||||
},
|
||||
|
||||
getSubfolders: function () {
|
||||
|
||||
return _.sortBy(_.filter(this.content, function (entry) {
|
||||
|
||||
return entry.isFolder();
|
||||
}), function (entry) {
|
||||
|
||||
return entry.absHref;
|
||||
});
|
||||
},
|
||||
|
||||
getStats: function () {
|
||||
|
||||
var folders = 0,
|
||||
files = 0;
|
||||
|
||||
_.each(this.content, function (entry) {
|
||||
|
||||
if (entry.isFolder()) {
|
||||
folders += 1;
|
||||
} else {
|
||||
files += 1;
|
||||
}
|
||||
});
|
||||
|
||||
var depth = 0,
|
||||
entry = this;
|
||||
|
||||
while (entry.parent) {
|
||||
depth += 1;
|
||||
entry = entry.parent;
|
||||
}
|
||||
|
||||
return {
|
||||
folders: folders,
|
||||
files: files,
|
||||
depth: depth
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
get: get
|
||||
};
|
||||
});
|
42
src/_h5ai/js/inc/parser/apache-autoindex.js
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
module.define('parser/apache-autoindex', [jQuery, 'core/format', 'model/entry'], function ($, format, Entry) {
|
||||
|
||||
var parseTableRow = function (absHref, tr) {
|
||||
|
||||
var $tds = $(tr).find('td'),
|
||||
$a = $tds.eq(1).find('a'),
|
||||
label = $a.text(),
|
||||
time = format.parseDate($tds.eq(2).text(), 'DD-MMM-YYYY HH:mm'),
|
||||
size = format.parseSize($tds.eq(3).text());
|
||||
|
||||
absHref = absHref + $a.attr('href');
|
||||
|
||||
return label === 'Parent Directory' ? null : Entry.get(absHref, time, size);
|
||||
},
|
||||
|
||||
parseTable = function (absHref, table) {
|
||||
|
||||
return _.compact(_.map($(table).find('td').closest('tr'), function (tr) {
|
||||
|
||||
return parseTableRow(absHref, tr);
|
||||
}));
|
||||
},
|
||||
|
||||
parse = function (absHref, html) {
|
||||
|
||||
var id = '#data-apache-autoindex',
|
||||
$html = $(html),
|
||||
$id = $html.filter(id);
|
||||
|
||||
if (!$id.length) {
|
||||
$id = $html.find(id);
|
||||
}
|
||||
|
||||
return parseTable(absHref, $id.find('table'));
|
||||
};
|
||||
|
||||
return {
|
||||
id: 'apache-autoindex',
|
||||
parse: parse
|
||||
};
|
||||
});
|
48
src/_h5ai/js/inc/parser/generic-json.js
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
module.define('parser/generic-json', [jQuery, 'core/settings', 'model/entry'], function ($, settings, Entry) {
|
||||
|
||||
// expectes an hash of the form
|
||||
// {
|
||||
// entries: [
|
||||
// {absHref: String, time: Number, size: Number, status: Number or "h5ai"}
|
||||
// ]
|
||||
// }
|
||||
|
||||
var parseJson = function (absHref, json) {
|
||||
|
||||
if (json.hasOwnProperty('customHeader')) {
|
||||
settings.custom.header = json.customHeader;
|
||||
}
|
||||
if (json.hasOwnProperty('customFooter')) {
|
||||
settings.custom.footer = json.customFooter;
|
||||
}
|
||||
|
||||
return _.map(json.entries, function (jsonEntry) {
|
||||
|
||||
return Entry.get(jsonEntry.absHref, jsonEntry.time, jsonEntry.size, jsonEntry.status);
|
||||
});
|
||||
},
|
||||
|
||||
parseJsonStr = function (absHref, jsonStr) {
|
||||
|
||||
return parseJson(absHref, JSON.parse($.trim(jsonStr) || '{}'));
|
||||
},
|
||||
|
||||
parse = function (absHref, html) {
|
||||
|
||||
var id = '#data-generic-json',
|
||||
$html = $(html),
|
||||
$id = $html.filter(id);
|
||||
|
||||
if (!$id.length) {
|
||||
$id = $html.find(id);
|
||||
}
|
||||
|
||||
return parseJsonStr(absHref, $id.text());
|
||||
};
|
||||
|
||||
return {
|
||||
id: 'generic-json',
|
||||
parse: parse
|
||||
};
|
||||
});
|
135
src/_h5ai/js/inc/view/extended.js
Normal file
@ -0,0 +1,135 @@
|
||||
|
||||
module.define('view/extended', [jQuery, 'core/settings', 'core/resource', 'core/format', 'core/event', 'core/entry'], function ($, allsettings, resource, format, event, entry) {
|
||||
|
||||
var defaults = {
|
||||
modes: ['details', 'icons'],
|
||||
setParentFolderLabels: false
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.view),
|
||||
|
||||
template = '<li class="entry">' +
|
||||
'<a>' +
|
||||
'<span class="icon small"><img /></span>' +
|
||||
'<span class="icon big"><img /></span>' +
|
||||
'<span class="label" />' +
|
||||
'<span class="date" />' +
|
||||
'<span class="size" />' +
|
||||
'</a>' +
|
||||
'</li>',
|
||||
hintTemplate = '<span class="hint"></span>',
|
||||
listTemplate = '<ul>' +
|
||||
'<li class="header">' +
|
||||
'<a class="icon"></a>' +
|
||||
'<a class="label" href="#"><span class="l10n-name"></span></a>' +
|
||||
'<a class="date" href="#"><span class="l10n-lastModified"></span></a>' +
|
||||
'<a class="size" href="#"><span class="l10n-size"></span></a>' +
|
||||
'</li>' +
|
||||
'</ul>',
|
||||
emptyTemplate = '<div class="empty l10n-empty">empty</div>',
|
||||
|
||||
|
||||
|
||||
// updates this single entry
|
||||
update = function (entry) {
|
||||
|
||||
if (entry.$extended && entry.status && entry.$extended.data('status') === entry.status) {
|
||||
return entry.$extended;
|
||||
}
|
||||
|
||||
var $html = $(template),
|
||||
$a = $html.find('a'),
|
||||
$imgSmall = $html.find('.icon.small img'),
|
||||
$imgBig = $html.find('.icon.big img'),
|
||||
$label = $html.find('.label'),
|
||||
$date = $html.find('.date'),
|
||||
$size = $html.find('.size'),
|
||||
icon16 = resource.icon(entry.type),
|
||||
icon48 = resource.icon(entry.type, true),
|
||||
escapedHref = entry.absHref.replace(/'/g, "%27").replace(/"/g, "%22");
|
||||
|
||||
$html
|
||||
.addClass(entry.isFolder() ? 'folder' : 'file')
|
||||
.data('entry', entry)
|
||||
.data('status', entry.status);
|
||||
|
||||
if (entry.isParentFolder) {
|
||||
icon16 = resource.icon('folder-parent');
|
||||
icon48 = resource.icon('folder-parent', true);
|
||||
if (!settings.setParentFolderLabels) {
|
||||
$label.addClass('l10n-parentDirectory');
|
||||
}
|
||||
$html.addClass('folder-parent');
|
||||
}
|
||||
|
||||
$a.attr('href', entry.absHref);
|
||||
$imgSmall.attr('src', icon16).attr('alt', entry.type);
|
||||
$imgBig.attr('src', icon48).attr('alt', entry.type);
|
||||
$label.text(entry.label);
|
||||
$date.data('time', entry.time).text(format.formatDate(entry.time));
|
||||
$size.data('bytes', entry.size).text(format.formatSize(entry.size));
|
||||
|
||||
if (entry.isFolder() && _.isNumber(entry.status)) {
|
||||
if (entry.status === 200) {
|
||||
$html.addClass('page');
|
||||
$imgSmall.attr('src', resource.icon('folder-page'));
|
||||
$imgBig.attr('src', resource.icon('folder-page', true));
|
||||
} else {
|
||||
$html.addClass('error');
|
||||
$label.append($(hintTemplate).text(' ' + entry.status + ' '));
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.$extended) {
|
||||
entry.$extended.replaceWith($html);
|
||||
}
|
||||
entry.$extended = $html;
|
||||
|
||||
return $html;
|
||||
},
|
||||
|
||||
onMouseenter = function () {
|
||||
|
||||
var entry = $(this).closest('.entry').data('entry');
|
||||
event.pub('entry.mouseenter', entry);
|
||||
},
|
||||
|
||||
onMouseleave = function () {
|
||||
|
||||
var entry = $(this).closest('.entry').data('entry');
|
||||
event.pub('entry.mouseleave', entry);
|
||||
},
|
||||
|
||||
// creates the view for entry content
|
||||
init = function (entry) {
|
||||
|
||||
var $extended = $('#extended'),
|
||||
$ul = $(listTemplate);
|
||||
|
||||
if (entry.parent) {
|
||||
$ul.append(update(entry.parent));
|
||||
}
|
||||
|
||||
_.each(entry.content, function (e) {
|
||||
|
||||
$ul.append(update(e));
|
||||
|
||||
e.fetchStatus(function (e) {
|
||||
|
||||
update(e);
|
||||
});
|
||||
});
|
||||
|
||||
$extended.append($ul);
|
||||
|
||||
if (entry.isEmpty()) {
|
||||
$extended.append($(emptyTemplate));
|
||||
}
|
||||
|
||||
$extended
|
||||
.on('mouseenter', '.entry a', onMouseenter)
|
||||
.on('mouseleave', '.entry a', onMouseleave);
|
||||
};
|
||||
|
||||
init(entry);
|
||||
});
|
35
src/_h5ai/js/inc/view/spacing.js
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
module.define('view/spacing', [jQuery, 'core/settings', 'core/event'], function ($, allsettings, event) {
|
||||
|
||||
var defaults = {
|
||||
maxWidth: 960,
|
||||
top: 50,
|
||||
right: "auto",
|
||||
bottom: 50,
|
||||
left: "auto"
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.spacing),
|
||||
|
||||
adjustSpacing = function () {
|
||||
|
||||
$('#content').css({
|
||||
'margin-top': settings.top + $('#topbar').outerHeight(),
|
||||
'margin-bottom': settings.bottom + $('#bottombar').outerHeight()
|
||||
});
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
$('#content').css({
|
||||
'max-width': settings.maxWidth,
|
||||
'margin-right': settings.right,
|
||||
'margin-left': settings.left
|
||||
});
|
||||
|
||||
event.sub('ready', adjustSpacing);
|
||||
$(window).on('resize', adjustSpacing);
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
77
src/_h5ai/js/inc/view/viewmode.js
Normal file
@ -0,0 +1,77 @@
|
||||
|
||||
module.define('view/viewmode', [jQuery, 'core/settings', 'core/resource', 'core/store'], function ($, allsettings, resource, store) {
|
||||
|
||||
var defaults = {
|
||||
modes: ['details', 'icons'],
|
||||
setParentFolderLabels: false
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.view),
|
||||
|
||||
storekey = 'h5ai.viewmode',
|
||||
|
||||
templates = {
|
||||
details: '<li id="viewdetails" class="view">' +
|
||||
'<a href="#">' +
|
||||
'<img src="' + resource.image('view-details') + '" alt="view-details" />' +
|
||||
'<span class="l10n-details">details</span>' +
|
||||
'</a>' +
|
||||
'</li>',
|
||||
icons: '<li id="viewicons" class="view">' +
|
||||
'<a href="#">' +
|
||||
'<img src="' + resource.image('view-icons') + '" alt="view-icons" />' +
|
||||
'<span class="l10n-icons">icons</span>' +
|
||||
'</a>' +
|
||||
'</li>'
|
||||
},
|
||||
|
||||
update = function (viewmode) {
|
||||
|
||||
var $viewDetails = $('#viewdetails'),
|
||||
$viewIcons = $('#viewicons'),
|
||||
$extended = $('#extended');
|
||||
|
||||
if (viewmode) {
|
||||
store.put(storekey, viewmode);
|
||||
} else {
|
||||
viewmode = store.get(storekey);
|
||||
}
|
||||
viewmode = $.inArray(viewmode, settings.modes) >= 0 ? viewmode : settings.modes[0];
|
||||
|
||||
$viewDetails.add($viewIcons).removeClass('current');
|
||||
if (viewmode === 'details') {
|
||||
$viewDetails.addClass('current');
|
||||
$extended.addClass('details-view').removeClass('icons-view').show();
|
||||
} else if (viewmode === 'icons') {
|
||||
$viewIcons.addClass('current');
|
||||
$extended.removeClass('details-view').addClass('icons-view').show();
|
||||
} else {
|
||||
$extended.hide();
|
||||
}
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
var $navbar = $('#navbar'),
|
||||
$extended = $('#extended');
|
||||
|
||||
settings.modes = _.intersection(settings.modes, defaults.modes);
|
||||
|
||||
if (settings.modes.length > 1) {
|
||||
_.each(['icons', 'details'], function (view) {
|
||||
if ($.inArray(view, settings.modes) >= 0) {
|
||||
$(templates[view])
|
||||
.appendTo($navbar)
|
||||
.on('click', 'a', function (event) {
|
||||
update(view);
|
||||
event.preventDefault();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
update();
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
@ -1,12 +0,0 @@
|
||||
|
||||
// @include "inc/lib/jquery.min.js"
|
||||
// @include "inc/lib/jquery.mousewheel.js"
|
||||
// @include "inc/lib/jquery.fracs-core.min.js"
|
||||
// @include "inc/lib/jquery.scrollpanel.js"
|
||||
// @include "inc/lib/jquery.qrcode.js"
|
||||
|
||||
// @include "inc/lib/amplify.min.js"
|
||||
// @include "inc/lib/base64.js"
|
||||
// @include "inc/lib/date.js"
|
||||
|
||||
// @include "inc/main.js"
|
4
src/_h5ai/js/modernizr.min.js
vendored
25
src/_h5ai/js/scripts.js
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
// libs
|
||||
// ----
|
||||
// @include "inc/lib/modernizr-2.5.3.min.js"
|
||||
// @include "inc/lib/moment-1.5.0.min.js"
|
||||
// @include "inc/lib/json2.js"
|
||||
// @include "inc/lib/base64.js"
|
||||
|
||||
// underscore libs
|
||||
// ---------------
|
||||
// @include "inc/lib/underscore-1.3.1.min.js"
|
||||
// @include "inc/lib/module.js"
|
||||
|
||||
// jQuery libs
|
||||
// -----------
|
||||
// @include "inc/lib/jquery-1.7.1.min.js"
|
||||
// @include "inc/lib/jquery.fracs-0.11.min.js"
|
||||
// @include "inc/lib/jquery.mousewheel-3.0.6.js"
|
||||
// @include "inc/lib/jquery.qrcode.js"
|
||||
// @include "inc/lib/jquery.scrollpanel.js"
|
||||
// @include "inc/lib/amplify-1.1.0.min.js"
|
||||
|
||||
// h5ai
|
||||
// ----
|
||||
// @include "inc/main.js"
|
@ -1,150 +1,125 @@
|
||||
<?php
|
||||
|
||||
function safe_dirname($path, $endWithSlash = false) {
|
||||
|
||||
$path = str_replace("\\", "/", dirname($path));
|
||||
return preg_match("#^(\w:)?/$#", $path) ? $path : (preg_replace('#/$#', '', $path) . ($endWithSlash ? "/" : ""));
|
||||
require_once(str_replace("\\", "/", __DIR__) . "/inc/H5ai.php");
|
||||
|
||||
|
||||
$h5ai = new H5ai();
|
||||
$options = $h5ai->getOptions();
|
||||
|
||||
|
||||
function json_exit($obj) {
|
||||
|
||||
$obj["code"] = 0;
|
||||
echo json_encode($obj);
|
||||
exit;
|
||||
}
|
||||
|
||||
define("H5AI_ABS_PATH", safe_dirname(safe_dirname(__FILE__)));
|
||||
function json_fail($code, $msg = "", $cond = true) {
|
||||
|
||||
function require_h5ai($lib) {
|
||||
|
||||
require_once(H5AI_ABS_PATH . $lib);
|
||||
}
|
||||
|
||||
|
||||
function fail($code, $msg, $cond = true) {
|
||||
if ($cond) {
|
||||
echo "$code: $msg";
|
||||
echo json_encode(array("code" => $code, "msg" => $msg));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
function checkKeys($keys) {
|
||||
function check_keys($keys) {
|
||||
$values = array();
|
||||
foreach ($keys as $key) {
|
||||
fail(1, "parameter '$key' is missing", !array_key_exists($key, $_REQUEST));
|
||||
json_fail(101, "parameter '$key' is missing", !array_key_exists($key, $_REQUEST));
|
||||
$values[] = $_REQUEST[$key];
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
|
||||
|
||||
require_h5ai("/php/inc/H5ai.php");
|
||||
$h5ai = new H5ai();
|
||||
$options = $h5ai->getOptions();
|
||||
list($action) = check_keys(array("action"));
|
||||
|
||||
|
||||
list($action) = checkKeys(array("action"));
|
||||
if ($action === "getthumbsrc") {
|
||||
|
||||
|
||||
if ($action === "httpcodes") {
|
||||
|
||||
list($hrefs) = checkKeys(array("hrefs"));
|
||||
|
||||
function getHttpCodes($h5ai, $hrefs) {
|
||||
|
||||
$codes = array();
|
||||
foreach ($hrefs as $href) {
|
||||
$href = trim($href);
|
||||
if (strlen($href) > 0) {
|
||||
$codes[$href] = $h5ai->getHttpCode($href);
|
||||
}
|
||||
}
|
||||
return $codes;
|
||||
if (!$options["thumbnails"]["enabled"]) {
|
||||
json_fail(1, "thumbnails disabled");
|
||||
}
|
||||
|
||||
$hrefs = preg_split("/;/", $hrefs);
|
||||
$codes = getHttpCodes($h5ai, $hrefs);
|
||||
list($srcAbsHref, $width, $height, $mode) = check_keys(array("href", "width", "height", "mode"));
|
||||
|
||||
echo count($codes) === 0 ? "{}" : json_encode($codes);
|
||||
}
|
||||
|
||||
|
||||
else if ($action === "thumb") {
|
||||
|
||||
fail(0, "thumbs are disabled", !$options["showThumbs"]);
|
||||
list($srcAbsHref, $width, $height, $mode) = checkKeys(array("href", "width", "height", "mode"));
|
||||
|
||||
require_h5ai("/php/inc/Thumbnail.php");
|
||||
require_h5ai("/php/inc/Image.php");
|
||||
H5ai::req_once("/php/inc/Thumbnail.php");
|
||||
H5ai::req_once("/php/inc/Image.php");
|
||||
|
||||
$srcAbsPath = $h5ai->getRootAbsPath() . rawurldecode($srcAbsHref);
|
||||
|
||||
if (!Thumbnail::isUsable()) {
|
||||
Image::showImage($srcAbsPath);
|
||||
exit;
|
||||
json_fail(2, "thumbnails not supported");
|
||||
}
|
||||
|
||||
$thumbnail = new Thumbnail($h5ai, $srcAbsHref, $mode, $width, $height);
|
||||
$thumbnail->create(1);
|
||||
if (file_exists($thumbnail->getPath())) {
|
||||
Image::showImage($thumbnail->getPath());
|
||||
} else {
|
||||
$image = new Image();
|
||||
$image->setSource($srcAbsPath);
|
||||
$image->thumb($mode, $width, $height);
|
||||
$image->showDest();
|
||||
if (!file_exists($thumbnail->getPath())) {
|
||||
json_fail(3, "thumbnail creation failed");
|
||||
}
|
||||
|
||||
json_exit(array("absHref" => $thumbnail->getHref()));
|
||||
}
|
||||
|
||||
|
||||
else if ($action === "tree") {
|
||||
else if ($action === "archive") {
|
||||
|
||||
list($href) = checkKeys(array("href"));
|
||||
json_fail(1, "downloads disabled", !$options["download"]["enabled"]);
|
||||
|
||||
require_h5ai("/php/inc/Tree.php");
|
||||
list($execution, $format, $hrefs) = check_keys(array("execution", "format", "hrefs"));
|
||||
|
||||
$absHref = trim($href);
|
||||
$absPath = $h5ai->getAbsPath($absHref);
|
||||
|
||||
$tree = new TreeEntry($h5ai, $absPath, $absHref);
|
||||
$tree->loadContent();
|
||||
|
||||
echo $tree->contentToHtml();
|
||||
}
|
||||
|
||||
|
||||
else if ($action === "zip") {
|
||||
|
||||
fail(0, "zipped download is disabled", !$options["zippedDownload"]);
|
||||
list($hrefs) = checkKeys(array("hrefs"));
|
||||
|
||||
require_h5ai("/php/inc/ZipIt.php");
|
||||
|
||||
$zipit = new ZipIt($h5ai);
|
||||
H5ai::req_once("/php/inc/Archive.php");
|
||||
$archive = new Archive($h5ai);
|
||||
|
||||
$hrefs = explode(":", trim($hrefs));
|
||||
$zipFile = $zipit->zip($hrefs);
|
||||
$target = $archive->create($execution, $format, $hrefs);
|
||||
|
||||
if (is_string($zipFile)) {
|
||||
$response = array('status' => 'ok', 'id' => basename($zipFile), 'size' => filesize($zipFile));
|
||||
} else {
|
||||
$response = array('status' => 'failed', 'code' => $zipFile);
|
||||
if (!is_string($target)) {
|
||||
json_fail($target, "package creation failed");
|
||||
}
|
||||
echo json_encode($response);
|
||||
|
||||
json_exit(array("id" => basename($target), "size" => filesize($target)));
|
||||
}
|
||||
|
||||
|
||||
else if ($action === "getzip") {
|
||||
else if ($action === "getarchive") {
|
||||
|
||||
list($id) = checkKeys(array("id"));
|
||||
fail(1, "zipped file not found: " . $id, !preg_match("/^h5ai-zip-/", $id));
|
||||
json_fail(1, "downloads disabled", !$options["download"]["enabled"]);
|
||||
|
||||
$zipFile = str_replace("\\", "/", sys_get_temp_dir()) . "/" . $id;
|
||||
fail(2, "zipped file not found: " . $id, !file_exists($zipFile));
|
||||
list($id, $as) = check_keys(array("id", "as"));
|
||||
json_fail(2, "file not found", !preg_match("/^h5ai-selection-/", $id));
|
||||
|
||||
$target = H5ai::normalize_path(sys_get_temp_dir(), true) . $id;
|
||||
json_fail(3, "file not found", !file_exists($target));
|
||||
|
||||
header("Content-Disposition: attachment; filename=\"h5ai-selection.zip\"");
|
||||
header("Content-Type: application/octet-stream");
|
||||
header("Content-Length: " . filesize($zipFile));
|
||||
header("Content-Length: " . filesize($target));
|
||||
header("Content-Disposition: attachment; filename=\"$as\"");
|
||||
header("Connection: close");
|
||||
readfile($zipFile);
|
||||
readfile($target);
|
||||
}
|
||||
|
||||
|
||||
else if ($action === "getchecks") {
|
||||
|
||||
$php = $h5ai->checks["php"];
|
||||
$cache = $php && $h5ai->checks["cache"];
|
||||
$temp = $php && $h5ai->checks["temp"];
|
||||
|
||||
json_exit(array(
|
||||
"php" => $php,
|
||||
"cache" => $cache,
|
||||
"thumbs" => $cache && $h5ai->checks["gd"],
|
||||
"temp" => $temp,
|
||||
"archive" => $temp && $h5ai->checks["archive"],
|
||||
"tar" => $temp && $h5ai->checks["tar"],
|
||||
"zip" => $temp && $h5ai->checks["zip"]
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
else {
|
||||
fail(1, "unsupported 'action' specified");
|
||||
json_fail(100, "unsupported action");
|
||||
}
|
||||
|
||||
|
||||
|
131
src/_h5ai/php/inc/Archive.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
class Archive {
|
||||
|
||||
private static $TAR_CMD = "$(cd [ROOTDIR] && tar --no-recursion -cf [TARGET] [DIRS] [FILES])";
|
||||
private static $ZIP_CMD = "$(cd [ROOTDIR] && zip [TARGET] [FILES])";
|
||||
|
||||
|
||||
private $h5ai, $dirs, $files, $sc401;
|
||||
|
||||
|
||||
public function __construct($h5ai) {
|
||||
|
||||
$this->h5ai = $h5ai;
|
||||
}
|
||||
|
||||
|
||||
public function create($execution, $format, $hrefs) {
|
||||
|
||||
$this->dirs = array();
|
||||
$this->files = array();
|
||||
$this->sc401 = false;
|
||||
|
||||
$this->addHrefs($hrefs);
|
||||
|
||||
if ($this->sc401) {
|
||||
return 401;
|
||||
} else if (count($this->dirs) === 0 && count($this->files) === 0) {
|
||||
return 404;
|
||||
}
|
||||
|
||||
$target = H5ai::normalize_path(sys_get_temp_dir(), true) . "h5ai-selection-" . microtime(true) . rand() . "." . $format;
|
||||
|
||||
try {
|
||||
if ($execution === "shell") {
|
||||
|
||||
if ($format === "tar") {
|
||||
$cmd = Archive::$TAR_CMD;
|
||||
} else if ($format === "zip") {
|
||||
$cmd = Archive::$ZIP_CMD;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
$cmd = str_replace("[ROOTDIR]", "\"" . $this->h5ai->getRootAbsPath() . "\"", $cmd);
|
||||
$cmd = str_replace("[TARGET]", "\"" . $target . "\"", $cmd);
|
||||
$cmd = str_replace("[DIRS]", count($this->dirs) ? "\"" . implode("\" \"", array_values($this->dirs)) . "\"" : "", $cmd);
|
||||
$cmd = str_replace("[FILES]", count($this->files) ? "\"" . implode("\" \"", array_values($this->files)) . "\"" : "", $cmd);
|
||||
|
||||
`$cmd`;
|
||||
|
||||
} else if ($execution === "php") {
|
||||
|
||||
$archive = new PharData($target);
|
||||
foreach ($this->dirs as $archivedDir) {
|
||||
$archive->addEmptyDir($archivedDir);
|
||||
}
|
||||
foreach ($this->files as $realFile => $archivedFile) {
|
||||
$archive->addFile($realFile, $archivedFile); // very, very slow :/
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exeption $err) {
|
||||
return 500;
|
||||
}
|
||||
|
||||
return @filesize($target) ? $target : null;
|
||||
}
|
||||
|
||||
|
||||
private function addHrefs($hrefs) {
|
||||
|
||||
foreach ($hrefs as $href) {
|
||||
|
||||
$d = H5ai::normalize_path(dirname($href), true);
|
||||
$n = basename($href);
|
||||
|
||||
$code = $this->h5ai->getHttpCode($d);
|
||||
if ($code == 401) {
|
||||
$this->sc401 = true;
|
||||
}
|
||||
|
||||
if ($code == "h5ai" && !$this->h5ai->ignoreThisFile($n)) {
|
||||
|
||||
$realFile = $this->h5ai->getAbsPath($href);
|
||||
$archivedFile = preg_replace("!^" . H5ai::normalize_path($this->h5ai->getRootAbsPath(), true) . "!", "", $realFile);
|
||||
|
||||
if (is_dir($realFile)) {
|
||||
$this->addDir($realFile, $archivedFile);
|
||||
} else {
|
||||
$this->addFile($realFile, $archivedFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function addFile($realFile, $archivedFile) {
|
||||
|
||||
if (is_readable($realFile)) {
|
||||
$this->files[$realFile] = $archivedFile;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function addDir($realDir, $archivedDir) {
|
||||
|
||||
$code = $this->h5ai->getHttpCode($this->h5ai->getAbsHref($realDir));
|
||||
if ($code == 401) {
|
||||
$this->sc401 = true;
|
||||
}
|
||||
|
||||
if ($code == "h5ai") {
|
||||
$this->dirs[] = $archivedDir;
|
||||
|
||||
$files = $this->h5ai->readDir($realDir);
|
||||
foreach ($files as $file) {
|
||||
|
||||
$realFile = $realDir . "/" . $file;
|
||||
$archivedFile = $archivedDir . "/" . $file;
|
||||
|
||||
if (is_dir($realFile)) {
|
||||
$this->addDir($realFile, $archivedFile);
|
||||
} else {
|
||||
$this->addFile($realFile, $archivedFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -1,55 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Crumb {
|
||||
|
||||
private $h5ai, $parts;
|
||||
|
||||
|
||||
public function __construct($h5ai) {
|
||||
|
||||
$this->h5ai = $h5ai;
|
||||
$this->parts = array();
|
||||
|
||||
$href = $h5ai->getAbsHref();
|
||||
while ($href !== "/") {
|
||||
$this->parts[] = $href;
|
||||
$href = safe_dirname($href, true);
|
||||
}
|
||||
$this->parts[] = "/";
|
||||
|
||||
$this->parts = array_reverse($this->parts);
|
||||
}
|
||||
|
||||
|
||||
public function toHtml() {
|
||||
|
||||
$html = "";
|
||||
$idx = 0;
|
||||
foreach($this->parts as $href) {
|
||||
$idx++;
|
||||
$classes = "crumb folder" . ($idx === 1 ? " domain" : "") . ($idx === count($this->parts) ? " current" : "");
|
||||
$image = $this->h5ai->image($idx === 1 ? "home" : "crumb");
|
||||
$label = $this->h5ai->getLabel($href);
|
||||
$hint = "";
|
||||
|
||||
$code = $this->h5ai->getHttpCode($href);
|
||||
$classes .= " checkedHttpCode";
|
||||
if ($code !== "h5ai") {
|
||||
if ($code === 200) {
|
||||
$hint = "<img class='hint' src='" . $this->h5ai->image("page") . "' alt='page' />";
|
||||
} else {
|
||||
$hint = "<span class='hint'>(" . $code . ")</span>";
|
||||
}
|
||||
}
|
||||
|
||||
$html .= "<li class='$classes'>\n";
|
||||
$html .= "\t<a href='$href'>\n";
|
||||
$html .= "\t\t<img src='$image' alt='>' /><span>" . $label . "</span>" . $hint . "\n";
|
||||
$html .= "\t</a>\n";
|
||||
$html .= "</li>\n";
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
class Customize {
|
||||
|
||||
private $customHeader, $customFooter;
|
||||
|
||||
|
||||
public function __construct($h5ai) {
|
||||
|
||||
$absPath = $h5ai->getAbsPath();
|
||||
$options = $h5ai->getOptions();
|
||||
$this->customHeader = $options["customHeader"] ? $absPath . "/" . $options["customHeader"] : false;
|
||||
$this->customFooter = $options["customFooter"] ? $absPath . "/" . $options["customFooter"] : false;
|
||||
}
|
||||
|
||||
|
||||
public function getHeader() {
|
||||
|
||||
return $this->getContent($this->customHeader, "header");
|
||||
}
|
||||
|
||||
|
||||
public function getFooter() {
|
||||
|
||||
return $this->getContent($this->customFooter, "footer");
|
||||
}
|
||||
|
||||
|
||||
private function getContent($file, $tag) {
|
||||
|
||||
return (is_string($file) && file_exists($file)) ? ("<$tag>" . file_get_contents($file) . "</$tag>") : "";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
105
src/_h5ai/php/inc/Entry.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
class Entry {
|
||||
|
||||
|
||||
private static $cache = array();
|
||||
|
||||
|
||||
public static function getCache() {
|
||||
|
||||
return Entry::$cache;
|
||||
}
|
||||
|
||||
|
||||
public static function get($h5ai, $absPath, $absHref) {
|
||||
|
||||
if (array_key_exists($absHref, Entry::$cache)) {
|
||||
return Entry::$cache[$absHref];
|
||||
}
|
||||
|
||||
return new Entry($h5ai, $absPath, $absHref);
|
||||
}
|
||||
|
||||
|
||||
public static function sort() {
|
||||
|
||||
uasort(Entry::$cache, function ($entry1, $entry2) {
|
||||
|
||||
return strcasecmp($entry1->absHref, $entry2->absHref);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public $h5ai, $absPath, $absHref, $date, $size, $isFolder, $parent;
|
||||
|
||||
|
||||
private function __construct($h5ai, $absPath, $absHref) {
|
||||
|
||||
$this->h5ai = $h5ai;
|
||||
|
||||
$this->absPath = H5ai::normalize_path($absPath);
|
||||
|
||||
$this->isFolder = is_dir($this->absPath);
|
||||
$this->absHref = H5ai::normalize_path($absHref, $this->isFolder);
|
||||
|
||||
$this->date = filemtime($this->absPath);
|
||||
|
||||
if ($this->isFolder) {
|
||||
$this->size = null;
|
||||
} else {
|
||||
$this->size = filesize($this->absPath);
|
||||
}
|
||||
|
||||
$this->parent = null;
|
||||
if ($this->absHref !== "/") {
|
||||
$this->parent = Entry::get($this->h5ai, H5ai::normalize_path(dirname($this->absPath)), H5ai::normalize_path(dirname($this->absHref), true));
|
||||
}
|
||||
|
||||
Entry::$cache[$this->absHref] = $this;
|
||||
}
|
||||
|
||||
|
||||
public function toJsonObject($withStatus) {
|
||||
|
||||
$obj = array(
|
||||
"absHref" => $this->absHref,
|
||||
"time" => ($this->date * 1000),
|
||||
"size" => $this->size
|
||||
);
|
||||
|
||||
if ($withStatus && $this->isFolder) {
|
||||
$obj["status"] = $this->h5ai->getHttpCode($this->absHref);
|
||||
}
|
||||
|
||||
return $obj;
|
||||
}
|
||||
|
||||
|
||||
public function getParent() {
|
||||
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
|
||||
public function getContent() {
|
||||
|
||||
$content = array();
|
||||
|
||||
if ($this->h5ai->getHttpCode($this->absHref) !== "h5ai") {
|
||||
return $content;
|
||||
}
|
||||
|
||||
$files = $this->h5ai->readDir($this->absPath);
|
||||
foreach ($files as $file) {
|
||||
$entry = Entry::get($this->h5ai, $this->absPath . "/" . $file, $this->absHref . rawurlencode($file));
|
||||
$content[$entry->absPath] = $entry;
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -1,152 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_h5ai("/php/inc/Thumbnail.php");
|
||||
|
||||
|
||||
class Entry {
|
||||
|
||||
private $h5ai, $label, $absPath, $absHref, $date, $isFolder, $type, $size;
|
||||
|
||||
|
||||
public function __construct($h5ai, $absPath, $absHref, $type = null, $label = null) {
|
||||
|
||||
$this->h5ai = $h5ai;
|
||||
$this->label = $label !== null ? $label : $this->h5ai->getLabel($absHref);
|
||||
$this->absPath = $this->h5ai->normalizePath($absPath, false);
|
||||
$this->isFolder = is_dir($this->absPath);
|
||||
$this->absHref = $this->h5ai->normalizePath($absHref, $this->isFolder);
|
||||
|
||||
$this->date = filemtime($this->absPath);
|
||||
|
||||
if ($this->isFolder) {
|
||||
$this->type = $type !== null ? $type : "folder";
|
||||
$this->size = "";
|
||||
} else {
|
||||
$this->type = $type !== null ? $type : $this->h5ai->getType($this->absPath);
|
||||
$this->size = filesize($this->absPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function isFolder() {
|
||||
|
||||
return $this->isFolder;
|
||||
}
|
||||
|
||||
|
||||
public function toHtml() {
|
||||
|
||||
$classes = "entry " . ($this->isFolder ? "folder " : "file ") . $this->type;
|
||||
$imgClass = "";
|
||||
$img = $this->type;
|
||||
$smallImg = $this->h5ai->icon($this->type);
|
||||
$bigImg = $this->h5ai->icon($this->type, true);
|
||||
$hint = "";
|
||||
|
||||
if ($this->isFolder && $this->type !== "folder-parent") {
|
||||
$code = $this->h5ai->getHttpCode($this->absHref);
|
||||
$classes .= " checkedHttpCode";
|
||||
if ($code !== "h5ai") {
|
||||
if ($code === 200) {
|
||||
$img = "folder-page";
|
||||
$smallImg = $this->h5ai->icon("folder-page");
|
||||
$bigImg = $this->h5ai->icon("folder-page", true);
|
||||
} else {
|
||||
$classes .= " error";
|
||||
$hint = "<span class='hint'> " . $code . " </span>";
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($this->h5ai->showThumbs() && in_array($this->type, $this->h5ai->getThumbTypes())) {
|
||||
$imgClass = " class='thumb' ";
|
||||
$thumbnail = new Thumbnail($this->h5ai, $this->absHref, "square", 16, 16);
|
||||
$thumbnail->create();
|
||||
$smallImg = file_exists($thumbnail->getPath()) ? $thumbnail->getHref() : $thumbnail->getLiveHref();
|
||||
$thumbnail = new Thumbnail($this->h5ai,$this->absHref, "rational", 96, 46);
|
||||
$thumbnail->create();
|
||||
$bigImg = file_exists($thumbnail->getPath()) ? $thumbnail->getHref() : $thumbnail->getLiveHref();
|
||||
}
|
||||
|
||||
$html = "\t<li class='" . $classes . "'>\n";
|
||||
$html .= "\t\t<a href='" . $this->absHref . "'>\n";
|
||||
$html .= "\t\t\t<span class='icon small'><img " . $imgClass . " src='" . $smallImg . "' alt='" . $img . "' /></span>\n";
|
||||
$html .= "\t\t\t<span class='icon big'><img " . $imgClass . " src='" . $bigImg . "' alt='" . $img . "' /></span>\n";
|
||||
$html .= "\t\t\t<span class='label'>" . $this->label . $hint . "</span>\n";
|
||||
$html .= "\t\t\t<span class='date' data-time='" . $this->date . "000'></span>\n";
|
||||
$html .= "\t\t\t<span class='size' data-bytes='" . $this->size . "'>" . $this->size . "</span>\n";
|
||||
$html .= "\t\t</a>\n";
|
||||
$html .= "\t</li>\n";
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Extended {
|
||||
|
||||
private $h5ai, $parent, $content;
|
||||
|
||||
|
||||
public function __construct($h5ai) {
|
||||
|
||||
$this->h5ai = $h5ai;
|
||||
$this->parent = null;
|
||||
$this->content = array();
|
||||
$this->loadContent();
|
||||
}
|
||||
|
||||
|
||||
private function loadContent() {
|
||||
|
||||
if ($this->h5ai->getAbsHref() !== "/") {
|
||||
$options = $this->h5ai->getOptions();
|
||||
$parentPath = safe_dirname($this->h5ai->getAbsPath());
|
||||
$parentHref = safe_dirname($this->h5ai->getAbsHref(), true);
|
||||
$label = $options["setParentFolderLabels"] === true ? $this->h5ai->getLabel($parentHref) : "<span class='l10n-parentDirectory'>Parent Directory</span>";
|
||||
$this->parent = new Entry($this->h5ai, $parentPath, $parentHref, "folder-parent", $label);
|
||||
}
|
||||
|
||||
$this->content = array();
|
||||
|
||||
$files = $this->h5ai->readDir($this->h5ai->getAbsPath());
|
||||
foreach ($files as $file) {
|
||||
$absPath = $this->h5ai->getAbsPath() . "/" . $file;
|
||||
$absHref = $this->h5ai->getAbsHref() . rawurlencode($file);
|
||||
$this->content[$absPath] = new Entry($this->h5ai, $absPath, $absHref);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function toHtml() {
|
||||
|
||||
$html = "<section id='extended' class='" . $this->h5ai->getView() . "-view clearfix'>\n";
|
||||
$html .= "<ul>\n";
|
||||
$html .= $this->generateHeaders();
|
||||
if ($this->parent !== null) {
|
||||
$html .= $this->parent->toHtml();
|
||||
}
|
||||
foreach($this->content as $entry) {
|
||||
$html .= $entry->toHtml();
|
||||
}
|
||||
$html .= "</ul>\n";
|
||||
if (count($this->content) === 0) {
|
||||
$html .= "<div class='empty l10n-empty'>empty</div>";
|
||||
}
|
||||
$html .= "<div class='no-match l10n-noMatch'>no match</div>";
|
||||
$html .="</section>";
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
private function generateHeaders() {
|
||||
|
||||
$html = "\t<li class='header'>\n";
|
||||
$html .= "\t\t<a class='icon'></a>\n";
|
||||
$html .= "\t\t<a class='label' href='#'><span class='l10n-name'>Name</span></a>\n";
|
||||
$html .= "\t\t<a class='date' href='#'><span class='l10n-lastModified'>Last modified</span></a>\n";
|
||||
$html .= "\t\t<a class='size' href='#'><span class='l10n-size'>Size</span></a>\n";
|
||||
$html .= "\t</li>\n";
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -1,52 +1,43 @@
|
||||
<?php
|
||||
|
||||
require_h5ai("/config.php");
|
||||
require_h5ai("/php/inc/Cache.php");
|
||||
|
||||
define("H5AI_ABS_PATH", H5ai::normalize_path(dirname(dirname(dirname(__FILE__)))));
|
||||
|
||||
|
||||
H5ai::req_once("/config.php");
|
||||
H5ai::req_once("/php/inc/Cache.php");
|
||||
H5ai::req_once("/php/inc/Entry.php");
|
||||
|
||||
|
||||
class H5ai {
|
||||
|
||||
private static $VIEWMODES = array("details", "icons");
|
||||
|
||||
private $h5aiAbsPath,
|
||||
$rootAbsPath, $ignore, $ignoreRE,
|
||||
$config, $options, $types, $langs,
|
||||
$cache,
|
||||
$rootAbsHref, $h5aiAbsHref, $domain,
|
||||
$absHref, $absPath,
|
||||
$view;
|
||||
public static final function normalize_path($path, $endWithSlash = false) {
|
||||
|
||||
|
||||
public function __construct() {
|
||||
|
||||
$this->h5aiAbsPath = H5AI_ABS_PATH;
|
||||
|
||||
global $H5AI_CONFIG;
|
||||
$this->rootAbsPath = $H5AI_CONFIG["ROOT_ABS_PATH"];
|
||||
$this->ignore = $H5AI_CONFIG["IGNORE"];
|
||||
$this->ignoreRE = $H5AI_CONFIG["IGNORE_PATTERNS"];
|
||||
|
||||
$this->config = $this->loadConfig($this->h5aiAbsPath . "/config.js");
|
||||
$this->options = $this->config["options"];
|
||||
$this->types = $this->config["types"];
|
||||
$this->langs = $this->config["langs"];
|
||||
|
||||
$this->cache = new Cache($this->h5aiAbsPath . "/cache");
|
||||
|
||||
$this->rootAbsHref = $this->options["rootAbsHref"];
|
||||
$this->h5aiAbsHref = $this->options["h5aiAbsHref"];
|
||||
$this->domain = getenv("HTTP_HOST");
|
||||
|
||||
$this->absHref = $this->normalizePath(preg_replace('/\\?.*/', '', getenv("REQUEST_URI")), true);
|
||||
$this->absPath = $this->getAbsPath($this->absHref);
|
||||
|
||||
$this->view = $this->options["viewmodes"][0];
|
||||
if (!in_array($this->view, H5ai::$VIEWMODES)) {
|
||||
$this->view = H5ai::$VIEWMODES[0];
|
||||
}
|
||||
$path = str_replace("\\", "/", $path);
|
||||
return preg_match("#^(\w:)?/$#", $path) ? $path : (preg_replace('#/$#', '', $path) . ($endWithSlash ? "/" : ""));
|
||||
}
|
||||
|
||||
|
||||
private function loadConfig($file) {
|
||||
public static final function req_once($lib) {
|
||||
|
||||
require_once(H5AI_ABS_PATH . $lib);
|
||||
}
|
||||
|
||||
|
||||
public static final function starts_with($sequence, $start) {
|
||||
|
||||
return strcasecmp(substr($sequence, 0, strlen($start)), $start) === 0;
|
||||
}
|
||||
|
||||
|
||||
public static final function ends_with($sequence, $end) {
|
||||
|
||||
return strcasecmp(substr($sequence, -strlen($end)), $end) === 0;
|
||||
}
|
||||
|
||||
|
||||
private static final function load_config($file) {
|
||||
|
||||
$str = file_exists($file) ? file_get_contents($file) : "";
|
||||
|
||||
@ -60,9 +51,47 @@ class H5ai {
|
||||
}
|
||||
|
||||
|
||||
public function getH5aiAbsPath() {
|
||||
|
||||
return $this->h5aiAbsPath;
|
||||
|
||||
private $h5aiAbsPath,
|
||||
$rootAbsPath, $ignore, $ignoreRE,
|
||||
$config, $options,
|
||||
$rootAbsHref, $h5aiAbsHref,
|
||||
$absHref, $absPath,
|
||||
$cache;
|
||||
|
||||
public $checks;
|
||||
|
||||
|
||||
public function __construct() {
|
||||
|
||||
$this->h5aiAbsPath = H5ai::normalize_path(H5AI_ABS_PATH);
|
||||
|
||||
global $H5AI_CONFIG;
|
||||
$this->rootAbsPath = H5ai::normalize_path($H5AI_CONFIG["ROOT_ABS_PATH"]);
|
||||
$this->ignore = $H5AI_CONFIG["IGNORE"];
|
||||
$this->ignoreRE = $H5AI_CONFIG["IGNORE_PATTERNS"];
|
||||
|
||||
$this->config = H5ai::load_config($this->h5aiAbsPath . "/config.js");
|
||||
$this->options = $this->config["options"];
|
||||
|
||||
$this->rootAbsHref = H5ai::normalize_path($this->options["rootAbsHref"], true);
|
||||
$this->h5aiAbsHref = H5ai::normalize_path($this->options["h5aiAbsHref"], true);
|
||||
|
||||
$this->absHref = H5ai::normalize_path(preg_replace('/\\?.*/', '', getenv("REQUEST_URI")), true);
|
||||
$this->absPath = $this->getAbsPath($this->absHref);
|
||||
|
||||
$this->cache = new Cache($this->h5aiAbsPath . "/cache");
|
||||
|
||||
$this->checks = array(
|
||||
"php" => version_compare(PHP_VERSION, "5.2.0") >= 0,
|
||||
"archive" => class_exists("PharData"),
|
||||
"gd" => GD_VERSION != "GD_VERSION",
|
||||
"cache" => is_writable($this->h5aiAbsPath . "/cache"),
|
||||
"temp" => is_writable(sys_get_temp_dir()),
|
||||
"tar" => preg_match("/tar$/", `which tar`) > 0,
|
||||
"zip" => preg_match("/zip$/", `which zip`) > 0
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -72,6 +101,12 @@ class H5ai {
|
||||
}
|
||||
|
||||
|
||||
public function getH5aiAbsPath() {
|
||||
|
||||
return $this->h5aiAbsPath;
|
||||
}
|
||||
|
||||
|
||||
public function getRootAbsHref() {
|
||||
|
||||
return $this->rootAbsHref;
|
||||
@ -84,54 +119,18 @@ class H5ai {
|
||||
}
|
||||
|
||||
|
||||
public function getDomain() {
|
||||
|
||||
return $this->domain;
|
||||
}
|
||||
|
||||
|
||||
public function getView() {
|
||||
|
||||
return $this->view;
|
||||
}
|
||||
|
||||
|
||||
public function api() {
|
||||
|
||||
return $this->h5aiAbsHref . "php/api.php";
|
||||
}
|
||||
|
||||
|
||||
public function image($id) {
|
||||
|
||||
return $this->h5aiAbsHref . "images/" . $id . ".png";
|
||||
}
|
||||
|
||||
|
||||
public function icon($id, $big = false) {
|
||||
|
||||
return $this->h5aiAbsHref . "icons/" . ($big ? "48x48" : "16x16") . "/" . $id . ".png";
|
||||
}
|
||||
|
||||
|
||||
public function getOptions() {
|
||||
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
|
||||
public function getLangs() {
|
||||
|
||||
return $this->langs;
|
||||
}
|
||||
|
||||
|
||||
public function normalizePath($path, $endWithSlash) {
|
||||
|
||||
return preg_match("#^(\w:)?/$#", $path) ? $path : (preg_replace('#/$#', '', $path) . ($endWithSlash ? "/" : ""));
|
||||
}
|
||||
|
||||
|
||||
public function getAbsHref($absPath = null, $endWithSlash = true) {
|
||||
|
||||
if ($absPath === null) {
|
||||
@ -146,7 +145,7 @@ class H5ai {
|
||||
$encodedParts[] = rawurlencode($part);
|
||||
}
|
||||
|
||||
return $this->normalizePath($this->rootAbsHref . implode("/", $encodedParts), $endWithSlash);
|
||||
return H5ai::normalize_path($this->rootAbsHref . implode("/", $encodedParts), $endWithSlash);
|
||||
}
|
||||
|
||||
|
||||
@ -158,51 +157,14 @@ class H5ai {
|
||||
|
||||
$absHref = substr($absHref, strlen($this->rootAbsHref));
|
||||
|
||||
return $this->normalizePath($this->rootAbsPath . "/" . rawurldecode($absHref), false);
|
||||
}
|
||||
|
||||
|
||||
public function showThumbs() {
|
||||
|
||||
return $this->options["showThumbs"] === true;
|
||||
}
|
||||
|
||||
|
||||
public function getThumbTypes() {
|
||||
|
||||
return $this->options["thumbTypes"];
|
||||
}
|
||||
|
||||
|
||||
public function getTitle() {
|
||||
|
||||
$title = $this->domain . rawurldecode($this->absHref);
|
||||
$title = preg_replace("/\/$/", "", $title);
|
||||
$title = preg_replace("/\//", " > ", $title);
|
||||
if ($this->absHref !== "/") {
|
||||
$title = basename($this->absPath) . " - " . $title;
|
||||
}
|
||||
return $title;
|
||||
}
|
||||
|
||||
|
||||
public function getType($absPath) {
|
||||
|
||||
foreach($this->types as $type => $exts) {
|
||||
foreach($exts as $ext) {
|
||||
if ($this->endsWith($absPath, $ext)) {
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "unknown";
|
||||
return H5ai::normalize_path($this->rootAbsPath . "/" . rawurldecode($absHref));
|
||||
}
|
||||
|
||||
|
||||
public function ignoreThisFile($file) {
|
||||
|
||||
// always ignore
|
||||
if ($file === "." || $file === ".." || $this->startsWith($file, '.ht')) {
|
||||
if ($file === "." || $file === ".." || H5ai::starts_with($file, '.ht')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -236,24 +198,6 @@ class H5ai {
|
||||
}
|
||||
|
||||
|
||||
public function getLabel($absHref) {
|
||||
|
||||
return $absHref === "/" ? $this->domain : rawurldecode(basename($absHref));
|
||||
}
|
||||
|
||||
|
||||
public function startsWith($sequence, $start) {
|
||||
|
||||
return strcasecmp(substr($sequence, 0, strlen($start)), $start) === 0;
|
||||
}
|
||||
|
||||
|
||||
public function endsWith($sequence, $end) {
|
||||
|
||||
return strcasecmp(substr($sequence, -strlen($end)), $end) === 0;
|
||||
}
|
||||
|
||||
|
||||
public function getHttpCode($absHref) {
|
||||
|
||||
//return $this->cachedHttpCode($absHref);
|
||||
@ -265,12 +209,7 @@ class H5ai {
|
||||
|
||||
$cached = $this->cache->get($absHref);
|
||||
if ($cached === false) {
|
||||
$folderStatus = $this->options["folderStatus"];
|
||||
if (array_key_exists($absHref, $folderStatus)) {
|
||||
$code = $folderStatus[$absHref];
|
||||
} else {
|
||||
$code = $this->fetchHttpCode($absHref);
|
||||
}
|
||||
$code = $this->fetchHttpCode($absHref);
|
||||
$cached = array("href" => $absHref, "code" => $code);
|
||||
$this->cache->set($absHref, $cached);
|
||||
}
|
||||
@ -280,6 +219,17 @@ class H5ai {
|
||||
|
||||
public function fetchHttpCode($absHref) {
|
||||
|
||||
if (!is_dir($this->getAbsPath($absHref))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->options["folderstatus"]["enabled"]) {
|
||||
$folders = $this->options["folderstatus"]["folders"];
|
||||
if (array_key_exists($absHref, $folders)) {
|
||||
return $folders[$absHref];
|
||||
}
|
||||
}
|
||||
|
||||
$contentType = "Content-Type:";
|
||||
$h5aiContentType = "Content-Type: text/html;h5ai=";
|
||||
$host = getenv("HTTP_HOST");
|
||||
@ -301,16 +251,53 @@ class H5ai {
|
||||
$content = fgets($socket);
|
||||
$code = intval(trim(substr($content, 9, 4)));
|
||||
if ($code === 200) {
|
||||
while (! $this->startsWith($content, $contentType)) {
|
||||
while (! H5ai::starts_with($content, $contentType)) {
|
||||
$content = fgets($socket);
|
||||
}
|
||||
if ($this->startsWith($content, $h5aiContentType)) {
|
||||
if (H5ai::starts_with($content, $h5aiContentType)) {
|
||||
$code = "h5ai";
|
||||
}
|
||||
}
|
||||
fclose($socket);
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
|
||||
private function fileExists($file) {
|
||||
|
||||
return is_string($file) && file_exists($file);
|
||||
}
|
||||
|
||||
|
||||
public function getGenericJson() {
|
||||
|
||||
$header = $this->options["custom"]["header"];
|
||||
$footer = $this->options["custom"]["footer"];
|
||||
$header = $this->fileExists($header ? $this->absPath . "/" . $header : null) ? $header : null;
|
||||
$footer = $this->fileExists($footer ? $this->absPath . "/" . $footer : null) ? $footer : null;
|
||||
|
||||
// collect and sort entries
|
||||
$folder = Entry::get($this, $this->absPath, $this->absHref);
|
||||
while ($folder !== null) {
|
||||
$folder->getContent();
|
||||
$folder = $folder->getParent();
|
||||
}
|
||||
Entry::sort();
|
||||
|
||||
$entries = array();
|
||||
foreach(Entry::getCache() as $entry) {
|
||||
$entries[] = $entry->toJsonObject(true);
|
||||
}
|
||||
|
||||
$json = array(
|
||||
"entries" => $entries,
|
||||
"customHeader" => $header,
|
||||
"customFooter" => $footer
|
||||
);
|
||||
|
||||
return json_encode($json) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -51,7 +51,15 @@ class Image {
|
||||
|
||||
$this->sourceFile = $filename;
|
||||
|
||||
list($this->width, $this->height, $this->type) = getimagesize($this->sourceFile);
|
||||
list($this->width, $this->height, $this->type) = @getimagesize($this->sourceFile);
|
||||
|
||||
if (!$this->width || !$this->height) {
|
||||
$this->sourceFile = null;
|
||||
$this->width = null;
|
||||
$this->height = null;
|
||||
$this->type = null;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->source = imagecreatefromstring(file_get_contents($this->sourceFile));
|
||||
}
|
||||
@ -99,6 +107,10 @@ class Image {
|
||||
|
||||
private function magic($destX, $destY, $srcX, $srcY, $destWidth, $destHeight, $srcWidth, $srcHeight, $canWidth = null, $canHeight = null, $color = null) {
|
||||
|
||||
if (is_null($this->source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_null($canWidth) && !is_null($canHeight)) {
|
||||
$this->dest = imagecreatetruecolor($canWidth, $canHeight);
|
||||
} else {
|
||||
@ -134,6 +146,10 @@ class Image {
|
||||
|
||||
public function squareThumb($width) {
|
||||
|
||||
if (is_null($this->source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$a = min($this->width, $this->height);
|
||||
$x = intval(($this->width - $a) / 2);
|
||||
$y = intval(($this->height - $a) / 2);
|
||||
@ -144,6 +160,10 @@ class Image {
|
||||
|
||||
public function rationalThumb($width, $height) {
|
||||
|
||||
if (is_null($this->source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = 1.0 * $this->width / $this->height;
|
||||
|
||||
$h = $height;
|
||||
@ -164,6 +184,10 @@ class Image {
|
||||
|
||||
public function centerThumb($width, $height, $color = null) {
|
||||
|
||||
if (is_null($this->source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = 1.0 * $this->width / $this->height;
|
||||
|
||||
$h = $height;
|
||||
@ -187,6 +211,10 @@ class Image {
|
||||
|
||||
public function freeThumb($width, $height) {
|
||||
|
||||
if (is_null($this->source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$w = intval($width);
|
||||
$h = intval($height);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
require_h5ai("/php/inc/Image.php");
|
||||
H5ai::req_once("/php/inc/Image.php");
|
||||
|
||||
|
||||
class Thumbnail {
|
||||
|
@ -1,158 +0,0 @@
|
||||
<?php
|
||||
|
||||
class TreeEntry {
|
||||
|
||||
private $h5ai, $label, $absPath, $absHref, $isFolder, $type, $content;
|
||||
|
||||
|
||||
public function __construct($h5ai, $absPath, $absHref, $type = null) {
|
||||
|
||||
$this->h5ai = $h5ai;
|
||||
|
||||
$this->label = $this->h5ai->getLabel($absHref);
|
||||
$this->absPath = $this->h5ai->normalizePath($absPath, false);
|
||||
$this->isFolder = is_dir($this->absPath);
|
||||
$this->absHref = $this->h5ai->normalizePath($absHref, $this->isFolder);
|
||||
|
||||
$this->type = $type !== null ? $type : ($this->isFolder ? "folder" : $this->h5ai->getType($this->absPath));
|
||||
$this->content = null;
|
||||
}
|
||||
|
||||
|
||||
public function loadContent() {
|
||||
|
||||
$this->content = array();
|
||||
|
||||
if ($this->h5ai->getHttpCode($this->absHref) !== "h5ai") {
|
||||
return;
|
||||
}
|
||||
|
||||
$files = $this->h5ai->readDir($this->absPath);
|
||||
foreach ($files as $file) {
|
||||
$tree = new TreeEntry($this->h5ai, $this->absPath . "/" . $file, $this->absHref . rawurlencode($file));
|
||||
|
||||
if ($tree->isFolder) {
|
||||
$this->content[$tree->absPath] = $tree;
|
||||
}
|
||||
}
|
||||
|
||||
$this->sort();
|
||||
}
|
||||
|
||||
|
||||
public function cmpTrees($t1, $t2) {
|
||||
|
||||
if ($t1->isFolder && !$t2->isFolder) {
|
||||
return -1;
|
||||
}
|
||||
if (!$t1->isFolder && $t2->isFolder) {
|
||||
return 1;
|
||||
}
|
||||
return strcasecmp($t1->absPath, $t2->absPath);
|
||||
}
|
||||
|
||||
|
||||
public function sort() {
|
||||
|
||||
if ($this->content !== null) {
|
||||
uasort($this->content, array($this, "cmpTrees"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function toHtml() {
|
||||
|
||||
$classes = "entry " . $this->type . ($this->absHref === $this->h5ai->getAbsHref() ? " current" : "");
|
||||
$icon = $this->type;
|
||||
if ($this->absHref === "/") {
|
||||
$icon = "folder-home";
|
||||
}
|
||||
$hint = "";
|
||||
$code = "h5ai";
|
||||
|
||||
if ($this->isFolder) {
|
||||
$code = $this->h5ai->getHttpCode($this->absHref);
|
||||
$classes .= " checkedHttpCode";
|
||||
if ($code !== "h5ai") {
|
||||
if ($code === 200) {
|
||||
$icon = "folder-page";
|
||||
$hint = "<span class='hint'><img src='" . $this->h5ai->image("page") . "' alt='page' /></span>";
|
||||
} else {
|
||||
$classes .= " error";
|
||||
$hint = "<span class='hint'> " . $code . " </span>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$html = "<div class='" . $classes ."'>\n";
|
||||
if ($this->content !== null && count($this->content) === 0 || $code !== "h5ai") {
|
||||
$html .= "<span class='blank'></span>\n";
|
||||
} else {
|
||||
$indicatorState = $this->content === null ? " unknown" : " open";
|
||||
$html .= "<span class='indicator" . $indicatorState . "'><img src='" . $this->h5ai->image("tree") . "' alt='>' /></span>\n";
|
||||
}
|
||||
$html .= "<a href='" . $this->absHref . "'>\n";
|
||||
$html .= "<span class='icon'><img src='" . $this->h5ai->icon($icon) . "' alt='" . $icon . "' /></span>";
|
||||
$html .= "<span class='label'>" . $this->label . "</span>" . $hint . "\n";
|
||||
$html .= "</a>\n";
|
||||
$html .= $this->contentToHtml();
|
||||
$html .= "</div>\n";
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
public function contentToHtml() {
|
||||
|
||||
$html = "<ul class='content'>\n";
|
||||
if ($this->content !== null) {
|
||||
foreach($this->content as $tree) {
|
||||
$html .= "<li>" . $tree->toHtml() . "</li>";
|
||||
}
|
||||
}
|
||||
$html .= "</ul>\n";
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
||||
public function getRoot() {
|
||||
|
||||
if ($this->absHref === "/") {
|
||||
return $this;
|
||||
};
|
||||
|
||||
$tree = new TreeEntry($this->h5ai, safe_dirname($this->absPath), safe_dirname($this->absHref, true));
|
||||
$tree->loadContent();
|
||||
$tree->content[$this->absPath] = $this;
|
||||
|
||||
return $tree->getRoot();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Tree {
|
||||
|
||||
private $h5ai;
|
||||
|
||||
|
||||
public function __construct($h5ai) {
|
||||
|
||||
$this->h5ai = $h5ai;
|
||||
}
|
||||
|
||||
|
||||
public function toHtml() {
|
||||
|
||||
$options = $this->h5ai->getOptions();
|
||||
if ($options["showTree"] === false) {
|
||||
return "";
|
||||
}
|
||||
|
||||
$tree = new TreeEntry($this->h5ai, $this->h5ai->getAbsPath(), $this->h5ai->getAbsHref());
|
||||
$tree->loadContent();
|
||||
$root = $tree->getRoot();
|
||||
return "<section id='tree'>\n" . $root->toHtml() . "</section>\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|