diff --git a/README.md b/README.md index f55984488..eca5869a1 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,12 @@ It uses the [Faenza icon set](http://tiheum.deviantart.com/art/Faenza-Icons-1733 ## Changelog +### v0.14 · *2011-08-16* + +* added image thumbnails for PHP version +* new option `slideTree` to turn off auto slide in + + ### v0.13.2 · *2011-08-12* * changes in `/h5ai/.htaccess` ... PHP configuration ... diff --git a/build.properties b/build.properties index 0044b806b..9f5699625 100644 --- a/build.properties +++ b/build.properties @@ -3,7 +3,7 @@ custom = true # project project.name = h5ai -project.version = 0.13.2 +project.version = 0.14 # src diff --git a/release/h5ai-0.14.tar.gz b/release/h5ai-0.14.tar.gz new file mode 100644 index 000000000..6fda4074f Binary files /dev/null and b/release/h5ai-0.14.tar.gz differ diff --git a/release/h5ai-0.14.zip b/release/h5ai-0.14.zip new file mode 100644 index 000000000..bc24e33ac Binary files /dev/null and b/release/h5ai-0.14.zip differ diff --git a/src/h5ai/.htaccess b/src/h5ai/.htaccess index c21ea0122..ec4f2924f 100644 --- a/src/h5ai/.htaccess +++ b/src/h5ai/.htaccess @@ -28,5 +28,8 @@ AddType text/html .php Header set Cache-Control "max-age=31449600, public" + + Header set Cache-Control "max-age=31449600, public" + diff --git a/src/h5ai/css/inc/extended.less b/src/h5ai/css/inc/extended.less index af1a18c49..12b3134f1 100644 --- a/src/h5ai/css/inc/extended.less +++ b/src/h5ai/css/inc/extended.less @@ -116,6 +116,18 @@ 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 { @@ -170,8 +182,8 @@ display: block; img { - width: 48px; - height: 48px; + min-width: 48px; + min-height: 48px; margin-bottom: 8px; } } @@ -206,6 +218,21 @@ } } } + &.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 { diff --git a/src/h5ai/js/inc/h5ai.js b/src/h5ai/js/inc/h5ai.js index 6650c6833..297efcc19 100644 --- a/src/h5ai/js/inc/h5ai.js +++ b/src/h5ai/js/inc/h5ai.js @@ -21,6 +21,7 @@ var H5ai = function ( options, langs ) { ascending: true }, showTree: true, + slideTree: true, folderStatus: { }, lang: null, @@ -182,7 +183,7 @@ var H5ai = function ( options, langs ) { var $tree = $( "#tree" ); var $extended = $( "#extended" ); - if ( $tree.outerWidth() < $extended.offset().left || forceVisible === true ) { + if ( this.config.slideTree && $tree.outerWidth() < $extended.offset().left || forceVisible === true ) { if ( dontAnimate === true ) { $tree.stop().css( { left: 0 } ); } else { diff --git a/src/h5ai/options.js b/src/h5ai/options.js index db1b1b8b2..46e705826 100644 --- a/src/h5ai/options.js +++ b/src/h5ai/options.js @@ -35,6 +35,11 @@ h5aiOptions = { */ "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 @@ -91,7 +96,13 @@ h5aiOptions = { * http://www.php.net/manual/en/function.preg-match.php */ "ignore": [ "h5ai", "h5ai.header.html", "h5ai.footer.html" ], - "ignoreRE": [ "/^\\./" ] + "ignoreRE": [ "/^\\./" ], + + /* + * Only used in PHP implementation. + * Show thumbnails in Icons view. + */ + "showThumbs": true }; diff --git a/src/h5ai/php/extended.php b/src/h5ai/php/extended.php index 7efba903f..838d771c9 100644 --- a/src/h5ai/php/extended.php +++ b/src/h5ai/php/extended.php @@ -1,7 +1,10 @@ type = $type !== null ? $type : $this->h5ai->getType( $this->absPath ); $this->size = filesize( $this->absPath ); } + + $this->thumbTypes = array( "bmp", "gif", "ico", "image", "jpg", "png", "tiff" ); } public function isFolder() { @@ -54,6 +59,8 @@ public function toHtml( $dateFormat ) { $classes = "entry " . $this->type; $img = $this->type; + $smallImg = "/h5ai/icons/16x16/" . $this->type . ".png"; + $bigImg = "/h5ai/icons/48x48/" . $this->type . ".png"; $hint = ""; $dateLabel = date( $dateFormat, $this->date ); @@ -63,17 +70,28 @@ public function toHtml( $dateFormat ) { if ( $code !== "h5ai" ) { if ( $code === 200 ) { $img = "folder-page"; + $smallImg = "/h5ai/icons/16x16/folder-page.png"; + $bigImg = "/h5ai/icons/48x48/folder-page.png"; } else { $classes .= " error"; $hint = " " . $code . " "; } } } + if ( $this->h5ai->showThumbs() && in_array( $this->type, $this->thumbTypes ) ) { + $classes .= " thumb"; + $thumbnail = new Thumbnail( $this->absPath, "square", 16, 16 ); + $thumbnail->create(); + $smallImg = file_exists( $thumbnail->getPath() ) ? $thumbnail->getHref() : $thumbnail->getLiveHref(); + $thumbnail = new Thumbnail( $this->absPath, "rational", 96, 46 ); + $thumbnail->create(); + $bigImg = file_exists( $thumbnail->getPath() ) ? $thumbnail->getHref() : $thumbnail->getLiveHref(); + } $html = "\t
  • \n"; $html .= "\t\t\n"; - $html .= "\t\t\t" . $img . "\n"; - $html .= "\t\t\t" . $img . "\n"; + $html .= "\t\t\t" . $img . "\n"; + $html .= "\t\t\t" . $img . "\n"; $html .= "\t\t\t" . $this->label . $hint . "\n"; $html .= "\t\t\t" . $dateLabel . "\n"; $html .= "\t\t\t" . $this->formatSize( $this->size ) . "\n"; diff --git a/src/h5ai/php/h5ai.php b/src/h5ai/php/h5ai.php index 50ccfd284..c027e2a53 100644 --- a/src/h5ai/php/h5ai.php +++ b/src/h5ai/php/h5ai.php @@ -83,7 +83,7 @@ public function getView() { public function getOptions() { - return $this->options["options"] ; + return $this->options["options"]; } public function getLangs() { @@ -117,6 +117,11 @@ public function getDateFormat() { return $this->dateFormat; } + public function showThumbs() { + + return $this->options["options"]["showThumbs"] === true; + } + public function getTitle() { $title = $this->domain . rawurldecode( $this->absHref ); @@ -187,12 +192,12 @@ public function normalizePath( $path, $endWithSlash ) { public function startsWith( $sequence, $start ) { - return substr( $sequence, 0, strlen( $start ) ) === $start; + return strcasecmp( substr( $sequence, 0, strlen( $start ) ), $start ) === 0; } public function endsWith( $sequence, $end ) { - return substr( $sequence, -strlen( $end ) ) === $end; + return strcasecmp( substr( $sequence, -strlen( $end ) ), $end ) === 0; } public function getHttpCode( $absHref ) { diff --git a/src/h5ai/php/image.php b/src/h5ai/php/image.php new file mode 100644 index 000000000..8ea342fe8 --- /dev/null +++ b/src/h5ai/php/image.php @@ -0,0 +1,202 @@ +sourceFile = null; + $this->source = null; + $this->width = null; + $this->height = null; + $this->type = null; + + $this->dest = null; + + $this->setSource( $filename ); + } + + + public function __destruct() { + + $this->releaseSource(); + $this->releaseDest(); + } + + + public function setSource( $filename ) { + + $this->releaseSource(); + $this->releaseDest(); + + if ( is_null( $filename ) ) + return; + + $this->sourceFile = $filename; + + list( $this->width, $this->height, $this->type ) = getimagesize( $this->sourceFile ); + + $this->source = imagecreatefromstring( file_get_contents( $this->sourceFile ) ); + } + + + public function showDest() { + + if ( !is_null( $this->dest ) ) { + header( "Content-type: image/jpeg" ); + imagejpeg( $this->dest, null, 100 ); + } + } + + + public function saveDest( $filename ) { + + if ( !is_null( $this->dest ) ) { + @imagejpeg( $this->dest, $filename, 90 ); + @chmod( $filename, 0775 ); + } + } + + + public function releaseDest() { + + if ( !is_null( $this->dest ) ) { + imagedestroy( $this->dest ); + $this->dest = null; + } + } + + + public function releaseSource() { + + if ( !is_null( $this->source ) ) { + imagedestroy( $this->source ); + $this->sourceFile = null; + $this->source = null; + $this->width = null; + $this->height = null; + $this->type = null; + } + } + + + public static function showImage( $filename ) { + + $image = file_get_contents( $filename ); + header( "content-type: image" ); + echo $image; + } + + + private function magic( $destX, $destY, $srcX, $srcY, $destWidth, $destHeight, $srcWidth, $srcHeight, $canWidth = null, $canHeight = null, $color = null ) { + + if ( !is_null( $canWidth ) && !is_null( $canHeight ) ) { + $this->dest = imagecreatetruecolor( $canWidth, $canHeight ); + } else { + $this->dest = imagecreatetruecolor( $destWidth, $destHeight ); + } + + if ( is_null( $color ) ) { + $color = array( 255, 255, 255 ); + } + $icol = imagecolorallocate( $this->dest, $color[0], $color[1], $color[2] ); + imagefill( $this->dest, 0, 0, $icol ); + + imagecopyresampled( $this->dest, $this->source, $destX, $destY, $srcX, $srcY, $destWidth, $destHeight, $srcWidth, $srcHeight ); + } + + + public function thumb( $mode, $width, $height = null, $color = null ) { + + if ( $height === null ) { + $height = $width; + } + if ( $mode === "square" ) { + $this->squareThumb( $width ); + } elseif ( $mode === "rational" ) { + $this->rationalThumb( $width, $height ); + } elseif ( $mode === "center" ) { + $this->centerThumb( $width, $height, $color ); + } else { + $this->freeThumb( $width, $height ); + } + } + + + public function squareThumb( $width ) { + + $a = min( $this->width, $this->height ); + $x = intval( ( $this->width - $a ) / 2 ); + $y = intval( ( $this->height - $a ) / 2 ); + + $this->magic( 0, 0, $x, $y, $width, $width, $a, $a ); + } + + + public function rationalThumb( $width, $height ) { + + $r = 1.0 * $this->width / $this->height; + + $h = $height; + $w = $r * $h; + + if ( $w > $width ) { + + $w = $width; + $h = 1.0 / $r * $w; + } + + $w = intval( $w ); + $h = intval( $h ); + + $this->magic( 0, 0, 0, 0, $w, $h, $this->width, $this->height ); + } + + + public function centerThumb( $width, $height, $color = null ) { + + $r = 1.0 * $this->width / $this->height; + + $h = $height; + $w = $r * $h; + + if ( $w > $width ) { + + $w = $width; + $h = 1.0 / $r * $w; + } + + $w = intval( $w ); + $h = intval( $h ); + + $x = intval( ( $width - $w ) / 2 ); + $y = intval( ( $height - $h ) / 2 ); + + $this->magic( $x, $y, 0, 0, $w, $h, $this->width, $this->height, $width, $height, $color ); + } + + + public function freeThumb( $width, $height ) { + + $w = intval( $width ); + $h = intval( $height ); + + $this->magic( 0, 0, 0, 0, $w, $h, $this->width, $this->height ); + } +} + +?> \ No newline at end of file diff --git a/src/h5ai/php/thumb.php b/src/h5ai/php/thumb.php new file mode 100644 index 000000000..47e5611b6 --- /dev/null +++ b/src/h5ai/php/thumb.php @@ -0,0 +1,26 @@ +create( 1 ); + if ( file_exists( $thumbnail->getPath() ) ) { + Image::showImage( $thumbnail->getPath() ); + } else { + $image = new Image(); + $image->setSource( $src ); + $image->thumb( $mode, $width, $height ); + $image->showDest(); + } + +?> \ No newline at end of file diff --git a/src/h5ai/php/thumbnail.php b/src/h5ai/php/thumbnail.php new file mode 100644 index 000000000..14d6f94fc --- /dev/null +++ b/src/h5ai/php/thumbnail.php @@ -0,0 +1,56 @@ +src = $src; + $this->width = $width; + $this->height = $height; + $this->mode = $mode; + $this->name = sha1( "$this->src-$this->width-$this->height-$this->mode" ); + $this->href = "/h5ai/cache/thumb-" . $this->name . ".jpg"; + $this->path = getenv( "DOCUMENT_ROOT" ) . $this->href; + $this->liveHref = "/h5ai/php/thumb.php?src=" . $this->src . "&width=" . $this->width . "&height=" . $this->height . "&mode=" . $this->mode; + } + + public function create( $force = 0 ) { + + if ( + $force === 2 + || ( $force === 1 && !file_exists( $this->path ) ) + || ( file_exists( $this->path ) && filemtime( $this->src ) >= filemtime( $this->path ) ) + ) { + $image = new Image(); + $image->setSource( $this->src ); + $image->thumb( $this->mode, $this->width, $this->height ); + $image->saveDest( $this->path ); + } + } + + public function getHref() { + + return $this->href; + } + + public function getPath() { + + return $this->path; + } + + public function getLiveHref() { + + return $this->liveHref; + } +} + +?> \ No newline at end of file