etiquette/templates/photo.html
Ethan Dalool 4838b26f3b Make photo info panel work better when it gets too big
Redo CSS so the left panel continues down the page instead of the background color just getting cut off; Keep the message_area from getting pinched into nothingness; improve narrow-screen CSS
2017-03-07 21:01:50 -08:00

396 lines
10 KiB
HTML

<!DOCTYPE html5>
<html>
<head>
{% import "header.html" as header %}
<title>Photo</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="/static/common.css">
<script src="/static/common.js"></script>
{% set filename = photo.id + photo.dot_extension %}
{% set link = "/file/" + filename %}
<style>
#content_body
{
/* Override common.css */
flex-direction: row;
flex: 1;
}
#left
{
display: flex;
flex-direction: column;
}
#right
{
flex: 1;
display: flex;
}
#editor_holder
{
max-width: 300px;
padding: 8px;
flex-direction: column;
background-color: rgba(0, 0, 0, 0.1);
}
#editor_area
{
flex: 3;
word-wrap: break-word;
}
#message_area
{
flex: 1;
}
.photo_viewer
{
display: flex;
flex: 1;
flex-direction: column;
justify-content: center;
align-items: center;
}
.photo_viewer a
{
display: flex;
justify-content: center;
align-items: center;
}
#photo_img_holder
{
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
background-repeat: no-repeat;
}
#photo_img_holder img
{
max-height: 100%;
max-width: 100%;
}
.photo_viewer audio
{
width: 100%;
}
.photo_viewer video
{
max-width: 100%;
max-height: 100%;
width: 100%;
}
#refresh_metadata_button
{
font-size: 11px;
}
@media screen and (max-width: 800px)
{
#content_body
{
/*
When flexing, it tries to contain itself entirely in the screen,
forcing #left and #right to squish together.
*/
flex: none;
flex-direction: column-reverse;
}
#left
{
/*
Display: None will be overridden as soon as the page detects that the
screen is in narrow mode and turns off the tag box's autofocus
*/
display: none;
width: initial;
max-width: none;
margin-top: 8px;
}
#right
{
flex: none;
height: calc(100% - 20px);
}
#editor_holder
{
display: flex;
flex-direction: row;
max-width: none;
}
#message_area
{
flex: 2;
height: initial;
max-height: none;
}
}
</style>
</head>
<body>
{{header.make_header(session=session)}}
<div id="content_body">
<div id="left">
<div id="editor_holder">
<div id="editor_area">
<!-- TAG INFO -->
<h4>Tags</h4>
<ul id="this_tags">
<li>
<input id="add_tag_textbox" type="text" autofocus>
<button id="add_tag_button" class="add_tag_button" onclick="submit_tag(receive_callback);">add</button>
</li>
{% set tags = photo.sorted_tags() %}
{% for tag in tags %}
<li>
<a class="tag_object" href="/search?tag_musts={{tag.name}}">{{tag.qualified_name()}}</a><!--
--><button
class="remove_tag_button"
onclick="remove_photo_tag('{{photo.id}}', '{{tag.name}}', receive_callback);">
</button>
</li>
{% endfor %}
</ul>
<!-- METADATA & DOWNLOAD -->
<h4>
File info
<button id="refresh_metadata_button" class="add_tag_button" onclick="refresh_metadata('{{photo.id}}');">refresh</button>
</h4>
<ul id="metadata">
{% if photo.author_id %}
{% set author = photo.author() %}
<li>Author: <a href="/user/{{author.username}}">{{author.username}}</a></li>
{% endif %}
{% if photo.width %}
<li>Dimensions: {{photo.width}}x{{photo.height}} px</li>
<li>Aspect ratio: {{photo.ratio}}</li>
{% endif %}
<li>Size: {{photo.bytestring()}}</li>
{% if photo.duration %}
<li>Duration: {{photo.duration_string()}}</li>
{% endif %}
<li><a href="/file/{{photo.id}}{{photo.dot_extension}}?download=1">Download as {{photo.id}}.{{photo.extension}}</a></li>
<li><a href="/file/{{photo.id}}{{photo.dot_extension}}?download=1&original_filename=1">Download as "{{photo.basename}}"</a></li>
</ul>
<!-- CONTAINING ALBUMS -->
{% set albums = photo.albums() %}
{% if albums %}
<h4>Albums containing this photo</h4>
<ul id="containing albums">
{% for album in albums %}
<li><a href="/album/{{album.id}}">{{album.title}}</a></li>
{% endfor %}
{% endif %}
</ul>
</div>
<div id="message_area">
</div>
</div>
</div>
<div id="right">
<!-- THE PHOTO ITSELF -->
<div class="photo_viewer">
{% if photo.simple_mimetype == "image" %}
<div id="photo_img_holder">
<img
id="photo_img"
src="{{link}}"
alt="{{photo.basename}}"
onclick="toggle_hoverzoom()"
onload="this.style.opacity=0.99"
>
</div>
{% elif photo.simple_mimetype == "video" %}
<video src="{{link}}" controls preload=none {%if photo.thumbnail%}poster="/thumbnail/{{photo.id}}.jpg"{%endif%}></video>
{% elif photo.simple_mimetype == "audio" %}
<audio src="{{link}}" controls></audio>
{% else %}
<a href="{{link}}">View {{filename}}</a>
{% endif %}
</div>
</div>
</div>
</body>
<script type="text/javascript">
var content_body = document.getElementById('content_body');
var add_tag_box = document.getElementById('add_tag_textbox');
var add_tag_button = document.getElementById('add_tag_button');
var message_area = document.getElementById('message_area');
add_tag_box.onkeydown = function(){entry_with_history_hook(add_tag_box, add_tag_button)};
function add_photo_tag(photoid, tagname, callback)
{
if (tagname === ""){return}
var url = "/photo/" + photoid + "/add_tag";
var data = new FormData();
data.append("tagname", tagname);
return post(url, data, callback);
}
function remove_photo_tag(photoid, tagname, callback)
{
if (tagname === ""){return}
var url = "/photo/" + photoid + "/remove_tag";
var data = new FormData();
data.append("tagname", tagname);
return post(url, data, callback);
}
function submit_tag(callback)
{
add_photo_tag('{{photo.id}}', add_tag_box.value, callback);
add_tag_box.value = "";
}
function receive_callback(response)
{
var message_text;
var message_positivity;
var tagname = response["tagname"];
if ("error_type" in response)
{
message_positivity = "message_negative";
message_text = response["error_message"];
}
else
{
var action;
message_positivity = "message_positive";
if (response["_request_url"].includes("add_tag"))
{
message_text = "Added tag " + tagname;
}
else if (response["_request_url"].includes("remove_tag"))
{
message_text = "Removed tag " + tagname;
}
else
{
return;
}
}
create_message_bubble(message_area, message_positivity, message_text, 8000);
}
function refresh_metadata(photoid)
{
var url= "/photo/" + photoid + "/refresh_metadata";
var data = new FormData();
post(url, data);
setTimeout(function(){location.reload();}, 2000);
}
function enable_hoverzoom()
{
console.log("enable");
div = document.getElementById("photo_img_holder");
img = document.getElementById("photo_img");
if (img.naturalWidth < div.offsetWidth && img.naturalHeight < div.offsetHeight)
{
return;
}
img.style.opacity = 0;
img.style.display = "none";
div.style.cursor = "zoom-out";
div.style.backgroundImage = "url('{{link}}')";
div.onmousemove = move_hoverzoom;
setTimeout(function(){div.onclick = disable_hoverzoom;}, 100);
return true;
}
function disable_hoverzoom()
{
console.log("disable");
div = document.getElementById("photo_img_holder");
img = document.getElementById("photo_img");
img.style.opacity = 100;
div.style.cursor = "";
img.style.display="";
div.style.backgroundImage = "none";
div.onmousemove = null;
div.onclick = null;
if (getComputedStyle(content_body).flexDirection != "column-reverse")
{
add_tag_box.focus();
}
}
function toggle_hoverzoom()
{
img = document.getElementById("photo_img");
if (img.style.opacity === "0")
{
disable_hoverzoom();
}
else
{
enable_hoverzoom();
}
}
photo_img_holder = document.getElementById("photo_img_holder");
photo_img = document.getElementById("photo_img");
function move_hoverzoom(event)
{
var x;
var y;
// Adding 5% to perceived position gives us a bit of padding around the image,
// so you don't need to navigate a 1px line to see the edge.
// We first subtract half of the image dimensions so that the 5% is applied
// to both left and right. Otherwise 105% of 0 is still 0 which doesn't
// apply padding on the left.
var mouse_x = event.offsetX;
mouse_x -= (photo_img_holder.offsetWidth / 2);
mouse_x *= 1.05;
mouse_x += (photo_img_holder.offsetWidth / 2);
var mouse_y = event.offsetY;
mouse_y -= (photo_img_holder.offsetHeight / 2);
mouse_y *= 1.05;
mouse_y += (photo_img_holder.offsetHeight / 2);
if (photo_img.naturalWidth < photo_img_holder.offsetWidth)
{
// If the image is smaller than the frame, just center it
x = (photo_img.naturalWidth - photo_img_holder.offsetWidth) / 2;
}
else
{
// Take the amount of movement necessary (frame width - image width)
// times our distance across the image as a percentage.
x = (photo_img.naturalWidth - photo_img_holder.offsetWidth) * (mouse_x / photo_img_holder.offsetWidth);
}
if (photo_img.naturalHeight < photo_img_holder.offsetHeight)
{
y = (photo_img.naturalHeight - photo_img_holder.offsetHeight) / 2;
}
else
{
y = (photo_img.naturalHeight - photo_img_holder.offsetHeight) * (mouse_y / photo_img_holder.offsetHeight);
}
//console.log(x);
photo_img_holder.style.backgroundPosition=(-x)+"px "+(-y)+"px";
}
setTimeout(
/*
When the screen is in column mode, the autofocusing of the tag box snaps the
screen down to it, which is annoying. By starting the #left hidden, we have
an opportunity to unset the autofocus before showing it.
*/
function()
{
var left = document.getElementById("left");
if (getComputedStyle(content_body).flexDirection == "column-reverse")
{
add_tag_box.autofocus = false;
}
left.style.display = "flex";
},
0
);
</script>
</html>