Port ClearSilver templates to Tornado.
This is a first stab, and yes, things are *UGLY*, particularly the JavaScript, which was written almost 10 years ago. As such, it pre-dates versions of IE that play nice with web standards, Promises and lots of other advancements. My knowledge of JavaScript has also greatly improved since then. :-)
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Vim swapfiles
|
||||||
|
*.swp
|
||||||
|
.*.swp
|
||||||
|
|
||||||
|
# Backup files
|
||||||
|
*~
|
||||||
|
|
||||||
|
# Python compiled files
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
__pycache__
|
||||||
|
|
||||||
|
# setuptools/distutils related
|
||||||
|
build
|
||||||
|
dist
|
23
LICENSE
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
Copyright (c) 2018, Stuart Longland
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
45
templates/gallery.thtml
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{% extends "master.thtml" %}
|
||||||
|
{# vim: set ts=8 noet sw=8 syn=html fileencoding=utf-8: #}
|
||||||
|
{% block html_head %}
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
margin-top: 200px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<title>Gallery: {{gallery_title}}</title>
|
||||||
|
{% end %}
|
||||||
|
{% block html_body %}
|
||||||
|
<table width="100%" class="controls">
|
||||||
|
<tr>
|
||||||
|
<td class="status"><a class="button"
|
||||||
|
accesskey="i" href="{{site_uri}}?{{page_query}}"
|
||||||
|
target="_top"><img alt="Index"
|
||||||
|
src="{{static_uri}}/templates/images/top.png"
|
||||||
|
border="0" align="absmiddle" /></a></td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="status">
|
||||||
|
<h1 align="center">{{gallery_title}}</h1>
|
||||||
|
<p align="center">{{gallery_desc}}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
{% if photos %}
|
||||||
|
{% for p in photos %}
|
||||||
|
{% set hw = p.thumbwidth / 2 %}
|
||||||
|
{% set hh = p.thumbheight / 2 %}
|
||||||
|
{% set xpad = 60 - hw %}
|
||||||
|
{% set ypad = 60 - hh %}
|
||||||
|
<a href="{{site_uri}}/{{gallery_name}}/{{p.name}}?{{page_query}}"><img src="{{p.thumbnail}}"
|
||||||
|
align="absmiddle"
|
||||||
|
width="{{p.thumbwidth}}"
|
||||||
|
height="{{p.thumbheight}}"
|
||||||
|
style="padding-left: {{xpad}}px; padding-right: {{xpad}}px; padding-top: {{ypad}}px; padding-bottom: {{ypad}}px;"
|
||||||
|
alt="{{p.annotation}}" /></a>
|
||||||
|
{% end %}
|
||||||
|
{% end %}
|
||||||
|
</p>
|
||||||
|
{% end %}
|
125
templates/generator.thtml
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
{% extends "master.thtml" %}
|
||||||
|
{# vim: set ts=8 noet sw=8 syn=html fileencoding=utf-8: #}
|
||||||
|
{% block html_head %}
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
margin: 2em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progress {
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
right: 0px;
|
||||||
|
border: 1px solid white;
|
||||||
|
padding: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#progdone {
|
||||||
|
color: white;
|
||||||
|
background-color: blue;
|
||||||
|
font-size: x-small;
|
||||||
|
text-align: center;
|
||||||
|
width: 0%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<title>Image: {{photo.annotation}} ?> ({{photo.name}})</title>
|
||||||
|
<script lang="type/javascript">
|
||||||
|
function display() {
|
||||||
|
if ( this.readyState == 4 ) {
|
||||||
|
document.photo.src = '';
|
||||||
|
document.last = document.data;
|
||||||
|
eval( 'document.data = (' + this.responseText + ');' );
|
||||||
|
var ratio = document.data.photo.origwidth /
|
||||||
|
document.data.photo.origheight;
|
||||||
|
if ( ratio > 1 ) {
|
||||||
|
document.photo.width = 400;
|
||||||
|
document.photo.height = 400/ratio;
|
||||||
|
} else {
|
||||||
|
document.photo.width = 300*ratio;
|
||||||
|
document.photo.height = 300;
|
||||||
|
}
|
||||||
|
document.photo.src = '{{static_uri}}/'
|
||||||
|
+ document.data.photo.resized;
|
||||||
|
var index = Math.floor(document.data.photo.index);
|
||||||
|
var count = Math.floor(document.data.gallery.length);
|
||||||
|
var progress = Math.round(
|
||||||
|
100*( index + 1 )
|
||||||
|
/ count );
|
||||||
|
document.progress.style.width = progress + '%';
|
||||||
|
document.progress.innerHTML = progress+'%';
|
||||||
|
document.xhr.onreadystatechange = display;
|
||||||
|
if ( ( document.data.photo.width <= 100 ) &&
|
||||||
|
( document.data.photo.height <= 100 ) ) {
|
||||||
|
document.xhr.open('GET',
|
||||||
|
'{{site_uri}}/'
|
||||||
|
+ document.data.gallery.name
|
||||||
|
+ '/'
|
||||||
|
+ document.data.photo.name
|
||||||
|
+ '?json=1'
|
||||||
|
+ document.scaledata);
|
||||||
|
} else {
|
||||||
|
document.lastphotolink.href =
|
||||||
|
'{{site_uri}}/'
|
||||||
|
+ document.data.gallery.name
|
||||||
|
+ '/'
|
||||||
|
+ document.last.photo.name;
|
||||||
|
document.lastphoto.src = '';
|
||||||
|
document.lastphoto.width =
|
||||||
|
document.photo.width;
|
||||||
|
document.lastphoto.height =
|
||||||
|
document.photo.height;
|
||||||
|
document.lastphoto.src = document.photo.src;
|
||||||
|
if ( document.data.photo.name !=
|
||||||
|
document.data.photo.next ) {
|
||||||
|
document.xhr.open('GET',
|
||||||
|
'{{site_uri}}/'
|
||||||
|
+ document.data.gallery.name
|
||||||
|
+ '/'
|
||||||
|
+ document.data.photo.next
|
||||||
|
+ '?json=1'
|
||||||
|
+ document.thumbdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.xhr.send(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
document.lastphotolink = document.getElementById('lastphotolink');
|
||||||
|
document.lastphoto = document.getElementById('lastphoto');
|
||||||
|
document.photo = document.getElementById('photo');
|
||||||
|
document.progress = document.getElementById('progdone');
|
||||||
|
document.base = window.location.protocol
|
||||||
|
+ window.location.host;
|
||||||
|
document.thumbdata = '&width=100&height=100&quality=25';
|
||||||
|
document.scaledata = '&width={{settings.width}}'
|
||||||
|
+ '&height={{settings.height}}'
|
||||||
|
+ '&quality={{settings.quality}}'
|
||||||
|
+ '&rotation={{settings.rotation}}';
|
||||||
|
|
||||||
|
document.xhr = getXHR();
|
||||||
|
document.xhr.onreadystatechange = display;
|
||||||
|
document.xhr.open('GET','{{site_uri}}/{{gallery.name}}/{{photo.name}}?json=1'+document.thumbdata);
|
||||||
|
document.xhr.send(null);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script lang="text/javascript" src="{{static_uri}}/templates/lib.js"></script>
|
||||||
|
<script lang="text/javascript" src="{{static_uri}}/templates/wheellib.js"></script>
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
{% block html_body %}
|
||||||
|
<div id="progress">
|
||||||
|
<div id="progdone"></div>
|
||||||
|
</div>
|
||||||
|
<a href="#" id="lastphotolink" target="_blank"> <img id="lastphoto"
|
||||||
|
alt="" width="400" height="300" /></a>
|
||||||
|
<img id="photo" alt="" width="400" height="300" />
|
||||||
|
<p>
|
||||||
|
Photo gallery images are being generated. Click the left photo
|
||||||
|
to view the last resized image.
|
||||||
|
</p>
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
{% block html_body_args %}onload="main();"'{% end %}
|
BIN
templates/images/back.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
templates/images/configure.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
templates/images/finish.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
templates/images/forward.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
templates/images/start.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
templates/images/top.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
templates/images/up.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
19
templates/index.thtml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{% extends "master.thtml" %}
|
||||||
|
{# vim: set ts=8 noet sw=8 syn=html fileencoding=utf-8: #}
|
||||||
|
{% block html_head %}
|
||||||
|
<title>{{site_name}}</title>
|
||||||
|
{% end %}
|
||||||
|
{% block html_body %}
|
||||||
|
<h1 align="center">{{site_name}}</h1>
|
||||||
|
|
||||||
|
{% if galleries %}
|
||||||
|
{% for g in galleries %}
|
||||||
|
<div style="border: 1px solid #ccc; display: block;">
|
||||||
|
<h2><a style="display: block; text-align: center; padding: 0.5em;"
|
||||||
|
href="{{site_uri}}/{{g.name}}?{{page_query}}">{{g.title}}</a></h2>
|
||||||
|
<p style="padding-left: 1em; padding-right: 1em; text-align: center;">{{g.desc}}</p>
|
||||||
|
</div>
|
||||||
|
<div style="height: 1em;"></div>
|
||||||
|
{% end %}
|
||||||
|
{% end %}
|
||||||
|
{% end %}
|
208
templates/lib.js
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
function getXHR() {
|
||||||
|
var httpRequest;
|
||||||
|
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
|
||||||
|
httpRequest = new XMLHttpRequest();
|
||||||
|
} else if (window.ActiveXObject) { // IE
|
||||||
|
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
|
||||||
|
}
|
||||||
|
return httpRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchImage( width, height, rotation ) {
|
||||||
|
data = getData();
|
||||||
|
xhr = getXHR();
|
||||||
|
photo_obj = document.getElementById( 'photoimg' );
|
||||||
|
|
||||||
|
xhr.onreadystatechange = function() {
|
||||||
|
if ( xhr.readyState == 4) {
|
||||||
|
document.scroll_en = true;
|
||||||
|
if ( xhr.status == 200 ) {
|
||||||
|
eval( 'data=' + xhr.responseText );
|
||||||
|
photo_obj.src =
|
||||||
|
data.uri + '/' + data.photo.resized;
|
||||||
|
document.data = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showPopupFor(3000, '<p class="popuptitle">Image Loaded</h4>'
|
||||||
|
+'<p class="popupbody">'
|
||||||
|
+'The image has been successfully retrieved.</p>');
|
||||||
|
document.scroll_en = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Cancel any existing timers */
|
||||||
|
if ( document.zoom_timer )
|
||||||
|
window.clearTimeout( document.zoom_timer );
|
||||||
|
|
||||||
|
/* Set a timer to fetch this data after a 3 second delay */
|
||||||
|
url = document.location.protocol + "//"
|
||||||
|
+ document.location.hostname
|
||||||
|
+ document.location.pathname
|
||||||
|
+ '?width=' + width
|
||||||
|
+ '&height=' + height
|
||||||
|
+ '&quality=' + data.settings.quality
|
||||||
|
+ '&rotation=' + rotation
|
||||||
|
+ '&json=1';
|
||||||
|
|
||||||
|
document.zoom_timer = window.setTimeout( function() {
|
||||||
|
document.scroll_en = false;
|
||||||
|
document.zoom_timer = false;
|
||||||
|
document.scroll_en = false;
|
||||||
|
showPopup('<p class="popuptitle">Loading Image</h4>'
|
||||||
|
+'<p class="popupbody">'
|
||||||
|
+'The requested image is being generated...'
|
||||||
|
+'Please Wait.</p>');
|
||||||
|
xhr.open('GET', url );
|
||||||
|
xhr.send(null);
|
||||||
|
}, 3000 );
|
||||||
|
}
|
||||||
|
|
||||||
|
function setZoom( zoom ) {
|
||||||
|
data = getData();
|
||||||
|
|
||||||
|
/* Round zoom to 1% */
|
||||||
|
zoom = Math.round( zoom*100 )/100;
|
||||||
|
|
||||||
|
document.zoom = zoom;
|
||||||
|
width = Math.round(data.photo.origwidth*zoom);
|
||||||
|
height = Math.round(data.photo.origheight*zoom);
|
||||||
|
|
||||||
|
document.getElementById( 'width' ).value = width;
|
||||||
|
document.getElementById( 'height' ).value = height;
|
||||||
|
|
||||||
|
photo_obj = document.getElementById( 'photoimg' );
|
||||||
|
if ( photo_obj ) {
|
||||||
|
photo_obj.width = width;
|
||||||
|
photo_obj.height = height;
|
||||||
|
|
||||||
|
/* If the size is bigger than our present image, request a
|
||||||
|
* bigger one from the server. */
|
||||||
|
if ( ( width > data.photo.width ) ||
|
||||||
|
( height > data.photo.height ) ) {
|
||||||
|
fetchImage( width, height, data.settings.rotation );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showPopupFor(3000,'<p class="popuptitle">Zoom Image</h4>'
|
||||||
|
+'<p class="popupbody">Zoom photo to '+zoom
|
||||||
|
+'x magnification.<br />'
|
||||||
|
+'Adjust using your mouse\'s scroll wheel then '
|
||||||
|
+'wait a moment to see the result.</p>');
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetZoom() {
|
||||||
|
data = getData();
|
||||||
|
if ( document.scroll_en )
|
||||||
|
setZoom( document.defaultZoom );
|
||||||
|
}
|
||||||
|
|
||||||
|
function adjustZoom( amount ) {
|
||||||
|
data = getData();
|
||||||
|
if ( document.zoom == null )
|
||||||
|
document.zoom = data.photo.zoom;
|
||||||
|
if ( document.scroll_en )
|
||||||
|
setZoom( document.zoom + amount );
|
||||||
|
}
|
||||||
|
|
||||||
|
function showPopup(body) {
|
||||||
|
if ( document.popupDiv )
|
||||||
|
div = document.popupDiv;
|
||||||
|
else {
|
||||||
|
div = document.popupDiv
|
||||||
|
= document.createElement('div');
|
||||||
|
|
||||||
|
div.style.position='absolute';
|
||||||
|
div.style.right='0px';
|
||||||
|
div.style.top='0px';
|
||||||
|
div.style.width='30em';
|
||||||
|
div.style.height='100px';
|
||||||
|
div.style.backgroundColor='#ccc';
|
||||||
|
div.style.color='black';
|
||||||
|
div.style.borderStyle='dotted';
|
||||||
|
div.style.borderColor='black';
|
||||||
|
div.style.borderWidth='2px';
|
||||||
|
div.style.visibility='hidden';
|
||||||
|
document.body.appendChild( div );
|
||||||
|
}
|
||||||
|
div.innerHTML = body;
|
||||||
|
div.style.visibility='visible';
|
||||||
|
}
|
||||||
|
|
||||||
|
function showPopupFor(duration, body) {
|
||||||
|
showPopup( body );
|
||||||
|
if ( document.popup_timer )
|
||||||
|
window.clearTimeout( document.popup_timer );
|
||||||
|
|
||||||
|
document.popup_timer = window.setTimeout( function() {
|
||||||
|
hidePopup();
|
||||||
|
}, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hidePopup() {
|
||||||
|
document.popupDiv.style.visibility='hidden';
|
||||||
|
}
|
||||||
|
|
||||||
|
function setRotation( angle ) {
|
||||||
|
data = getData();
|
||||||
|
|
||||||
|
/* Display a preview */
|
||||||
|
preview = document.location.protocol + "//"
|
||||||
|
+ document.location.hostname
|
||||||
|
+ data.CGI.ScriptName
|
||||||
|
+ '/.rotate_preview'
|
||||||
|
+ '?gallery=' + data.gallery.name
|
||||||
|
+ '&photo=' + data.photo.name
|
||||||
|
+ '&rotation=' + angle;
|
||||||
|
|
||||||
|
if ( preview == document.rotationPreview )
|
||||||
|
return;
|
||||||
|
|
||||||
|
showPopup('<img alt="preview" src="'+preview
|
||||||
|
+'" width="100" height="100" align="right" />'
|
||||||
|
+'<p class="popuptitle">Rotate Photo</p>'
|
||||||
|
+'<p class="popupbody">Rotate photo by '+angle
|
||||||
|
+' degrees.<br />'
|
||||||
|
+'Adjust using your mouse\'s scroll wheel then '
|
||||||
|
+'wait a moment to see the result.</p>');
|
||||||
|
|
||||||
|
/* Schedule actual image fetch */
|
||||||
|
fetchImage( data.photo.width, data.photo.height, angle );
|
||||||
|
rotatefield = document.getElementById( 'rotate' );
|
||||||
|
if ( rotatefield ) {
|
||||||
|
rotatefield.value = angle;
|
||||||
|
}
|
||||||
|
document.rotationPreview = preview;
|
||||||
|
document.rotation = angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
function adjustRotation(amount) {
|
||||||
|
data = getData();
|
||||||
|
setRotation( parseFloat(document.rotation) + amount );
|
||||||
|
}
|
||||||
|
|
||||||
|
function wheelHandler( delta ) {
|
||||||
|
pan=Math.round(document.getElementById('wheelPan').value);
|
||||||
|
zoom=Math.round(document.getElementById('wheelZoom').value)/100;
|
||||||
|
angle=parseFloat(document.getElementById('wheelRotate').value);
|
||||||
|
|
||||||
|
if ( document.getElementById('wheelActionZoom').checked )
|
||||||
|
if ( document.scroll_en )
|
||||||
|
adjustZoom( delta * zoom );
|
||||||
|
if ( document.getElementById('wheelActionHPan').checked )
|
||||||
|
window.scrollBy( -delta*pan, 0 );
|
||||||
|
if ( document.getElementById('wheelActionVPan').checked )
|
||||||
|
window.scrollBy( 0, -delta*pan );
|
||||||
|
|
||||||
|
if ( document.getElementById('wheelActionRotate').checked )
|
||||||
|
if ( document.scroll_en )
|
||||||
|
adjustRotation( -delta*angle );
|
||||||
|
}
|
||||||
|
document.scroll_en = true;
|
||||||
|
|
||||||
|
function toggleadj() {
|
||||||
|
if ( document.adjpanel ) {
|
||||||
|
document.getElementById('controls').appendChild(document.adjpanel);
|
||||||
|
delete( document.adjpanel );
|
||||||
|
} else {
|
||||||
|
document.adjpanel = document.getElementById('adjpanel');
|
||||||
|
document.getElementById('controls').deleteRow(2);
|
||||||
|
}
|
||||||
|
}
|
13
templates/master.thtml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
{# vim: set ts=8 noet sw=8 syn=html fileencoding=utf-8: #}
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="{{static_uri}}/templates/style.css"
|
||||||
|
type="text/css" />
|
||||||
|
{% block html_head %}{% end %}
|
||||||
|
</head>
|
||||||
|
<body {% block html_body_args %}{% end %}>
|
||||||
|
{% block html_body %}{% end %}
|
||||||
|
</body>
|
||||||
|
</html>
|
162
templates/photo.thtml
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
{% extends "master.thtml" %}
|
||||||
|
{% from json import dumps %}
|
||||||
|
{# vim: set ts=8 noet sw=8 syn=html fileencoding=utf-8: #}
|
||||||
|
{% block html_head %}
|
||||||
|
<style type="text/css">
|
||||||
|
body {
|
||||||
|
margin-top: 100px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<title>Image: {{photo.annotation}} ({{photo.name}})</title>
|
||||||
|
<script lang="type/javascript">
|
||||||
|
function getData() {
|
||||||
|
var data = {
|
||||||
|
CGI: {
|
||||||
|
ScriptName: {{ dumps(CGI.ScriptName) }}
|
||||||
|
},
|
||||||
|
gallery: {
|
||||||
|
name: {{ dumps(gallery.name) }},
|
||||||
|
title: {{ dumps(gallery.title) }},
|
||||||
|
desc: {{ dumps(gallery.desc) }},
|
||||||
|
first: {{ dumps(gallery.first) }},
|
||||||
|
last: {{ dumps(gallery.last) }}
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
width: {{settings.width}},
|
||||||
|
height: {{settings.height}},
|
||||||
|
quality: {{settings.quality}},
|
||||||
|
rotation: {{settings.rotation}}-0
|
||||||
|
},
|
||||||
|
photo: {
|
||||||
|
origwidth: {{photo.origwidth}},
|
||||||
|
origheight: {{photo.origheight}},
|
||||||
|
width: {{photo.width}},
|
||||||
|
height: {{photo.height}},
|
||||||
|
annotation: {{ dumps(photo.annotation) }},
|
||||||
|
thumbnail: {{ dumps(photo.thumbnails) }},
|
||||||
|
resized: {{ dumps(photo.resized) }},
|
||||||
|
name: {{ dumps(photo.name) }},
|
||||||
|
previous: {{ dumps(photo.previous) }},
|
||||||
|
next: {{ dumps(photo.next) }},
|
||||||
|
zoom: Math.round( 100*({{photo.width}}) /
|
||||||
|
{{photo.origwidth}})/100
|
||||||
|
}};
|
||||||
|
if ( document.data )
|
||||||
|
data = document.data;
|
||||||
|
else
|
||||||
|
document.data = data;
|
||||||
|
return( data );
|
||||||
|
}
|
||||||
|
document.defaultZoom =
|
||||||
|
Math.round( 100*({{photo.width}}) /
|
||||||
|
{{photo.origwidth}})/100;
|
||||||
|
document.rotation = {{settings.rotation}}-0;
|
||||||
|
</script>
|
||||||
|
<script lang="text/javascript" src="{{static_uri}}/templates/lib.js"></script>
|
||||||
|
<script lang="text/javascript" src="{{static_uri}}/templates/wheellib.js"></script>
|
||||||
|
{% end %}
|
||||||
|
{% block html_body %}
|
||||||
|
<table width="100%" class="controls" id="controls">
|
||||||
|
<tr>
|
||||||
|
<td class="firstlink"><a class="button" accesskey="["
|
||||||
|
href="{{site_uri}}/{{gallery.name}}/{{gallery.first}}?{{page_query}}"><img
|
||||||
|
alt="|<- First" src="{{static_uri}}/templates/images/start.png"
|
||||||
|
border="0" align="absmiddle" /></a></td>
|
||||||
|
<td class="prevlink"><a class="button" accesskey=","
|
||||||
|
href="{{site_uri}}/{{gallery.name}}/{{photo.previous}}?{{page_query}}"><img
|
||||||
|
alt="<- Prev" src="{{uri}}/templates/images/back.png"
|
||||||
|
border="0" align="absmiddle" /></a></td>
|
||||||
|
<td class="status"><a class="button" accesskey="l"
|
||||||
|
href="{{site_uri}}/{{gallery.name}}?{{page_query}}" target="_top"><img
|
||||||
|
alt="Album" src="{{static_uri}}/templates/images/up.png"
|
||||||
|
border="0" align="absmiddle" /></a></td>
|
||||||
|
<td class="status"><a class="button" accesskey="a"
|
||||||
|
href="#adjust" target="_top" onclick="toggleadj();"><img
|
||||||
|
alt="Adjust" src="{{static_uri}}/templates/images/configure.png"
|
||||||
|
border="0" align="absmiddle" /></a></td>
|
||||||
|
<td class="status"><a class="button" accesskey="i"
|
||||||
|
href="{{site_uri}}?{{page_query}}"
|
||||||
|
target="_top"><img alt="Index"
|
||||||
|
src="{{static_uri}}/templates/images/top.png"
|
||||||
|
border="0" align="absmiddle" /></a></td>
|
||||||
|
<td class="nextlink"><a class="button" accesskey="."
|
||||||
|
href="{{site_uri}}/{{gallery.name}}/{{photo.next}}?{{page_query}}"><img alt="-> Next" src="{{static_uri}}/templates/images/forward.png" border="0"
|
||||||
|
align="absmiddle" /></a></td>
|
||||||
|
<td class="lastlink"><a class="button" accesskey="]"
|
||||||
|
href="{{site_uri}}/{{gallery.name}}/{{gallery.last}}?{{page_query}}"><img
|
||||||
|
alt="->| Last" src="{{static_uri}}/templates/images/finish.png"
|
||||||
|
border="0" align="absmiddle" /></a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="status" colspan="7">
|
||||||
|
{{photo.annotation}} ({{photo.name}})
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="adjpanel">
|
||||||
|
<td colspan="7" class="status">
|
||||||
|
<form>
|
||||||
|
<a name="adjust"></a>
|
||||||
|
Resize: <input type="text" name="width" id="width"
|
||||||
|
value="{{photo.width}}" size="3" /> x
|
||||||
|
<input type="text" name="height" id="height"
|
||||||
|
value="{{photo.height}}" size="3" />
|
||||||
|
Rotation:
|
||||||
|
<input type="text" name="rotation" id="rotate"
|
||||||
|
value="0.000" size="5" />
|
||||||
|
Quality: <input type="text" name="quality"
|
||||||
|
value="60" size="3" />
|
||||||
|
(100% = PNG)
|
||||||
|
<input type="submit" value="Go" />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
Zoom:
|
||||||
|
<a href="#" onclick="adjustZoom( -0.1 );">[-0.1]</a>
|
||||||
|
<a href="#" onclick="adjustZoom( -0.01 );">[-0.01]</a>
|
||||||
|
<a href="#" onclick="setZoom( 1.0 );">[1.0]</a>
|
||||||
|
<a href="#" onclick="adjustZoom( 0.01 );">[+0.01]</a>
|
||||||
|
<a href="#" onclick="adjustZoom( 0.1 );">[+0.1]</a>
|
||||||
|
<a href="#" onclick="resetZoom();">[reset]</a><br />
|
||||||
|
|
||||||
|
Mouse wheel action:
|
||||||
|
<input type="radio" name="wheelAction"
|
||||||
|
value="zoom"
|
||||||
|
id="wheelActionZoom" />
|
||||||
|
<label for="wheelActionZoom">Zoom</label>
|
||||||
|
by <input type="text" name="wheelZoom" size="2"
|
||||||
|
value="1" id="wheelZoom" />%
|
||||||
|
or
|
||||||
|
<input type="radio" name="wheelAction"
|
||||||
|
value="hpan"
|
||||||
|
id="wheelActionHPan" />
|
||||||
|
<label for="wheelActionHPan">HPan</label>
|
||||||
|
<input type="radio" name="wheelAction"
|
||||||
|
value="vpan" checked
|
||||||
|
id="wheelActionVPan" />
|
||||||
|
<label for="wheelActionVPan">VPan</label>
|
||||||
|
by <input type="text" name="wheelPan" size="2"
|
||||||
|
value="50" id="wheelPan" /> pixels
|
||||||
|
|
||||||
|
or
|
||||||
|
<input type="radio" name="wheelAction"
|
||||||
|
value="rotate"
|
||||||
|
id="wheelActionRotate" />
|
||||||
|
<label for="wheelActionRotate">Rotate</label>
|
||||||
|
by <input type="text" name="wheelRotate" size="2"
|
||||||
|
value="1" id="wheelRotate" /> degrees
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<p align="center"><img id="photoimg"
|
||||||
|
width="{{photo.width}}"
|
||||||
|
height="{{photo.height}}"
|
||||||
|
src="{{static_uri}}/{{photo.resized}}"
|
||||||
|
alt="{{photo.annotation}}"
|
||||||
|
lowsrc="{{static_uri}}/{{photo.thumbnail}}" /></p>
|
||||||
|
|
||||||
|
<div class="photodesc">
|
||||||
|
{{photo.description}}
|
||||||
|
</div>
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
{% block html_body_args %}onload="toggleadj();"{% end %}
|
86
templates/style.css
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
@media screen {
|
||||||
|
body {
|
||||||
|
margin: 10px;
|
||||||
|
background-color: #333;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
position: fixed;
|
||||||
|
background-color: #333;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #333;
|
||||||
|
border: 1px solid white;
|
||||||
|
color: white;
|
||||||
|
padding: 0.5em;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: large;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover {
|
||||||
|
background-color: #666;
|
||||||
|
color: #fc9;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.firstlink, td.prevlink, td.nextlink, td.lastlink {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #c96;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #ffc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
visibility: hidden;
|
||||||
|
position: fixed;
|
||||||
|
height: 0px;
|
||||||
|
width: 0px;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnail {
|
||||||
|
border: 2px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnail:hover {
|
||||||
|
border: 2px solid #fec;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
padding-top: 0.5em;
|
||||||
|
padding-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popuptitle {
|
||||||
|
text-align: center;
|
||||||
|
font-size: large;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popupbody {
|
||||||
|
text-align: center;
|
||||||
|
height: 80px;
|
||||||
|
}
|
25
templates/wheellib.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* Source: http://adomas.org/javascript-mouse-wheel/ */
|
||||||
|
function wheel(event){
|
||||||
|
var delta = 0;
|
||||||
|
if (!event) /* For IE. */
|
||||||
|
event = window.event;
|
||||||
|
if (event.wheelDelta) { /* IE/Opera. */
|
||||||
|
delta = event.wheelDelta/120;
|
||||||
|
if (window.opera)
|
||||||
|
delta = -delta;
|
||||||
|
} else if (event.detail) { /** Mozilla case. */
|
||||||
|
delta = -event.detail/3;
|
||||||
|
}
|
||||||
|
if (delta)
|
||||||
|
wheelHandler(delta);
|
||||||
|
if (event.preventDefault)
|
||||||
|
event.preventDefault();
|
||||||
|
event.returnValue = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.addEventListener)
|
||||||
|
/** DOMMouseScroll is for mozilla. */
|
||||||
|
window.addEventListener('DOMMouseScroll', wheel, false);
|
||||||
|
else
|
||||||
|
/** IE/Opera. */
|
||||||
|
window.onmousewheel = document.onmousewheel = wheel;
|