etiquette/templates/photo.html

358 lines
9.7 KiB
HTML
Raw Normal View History

2016-09-18 08:33:46 +00:00
<!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 %}
2016-10-30 01:46:23 +00:00
{% set link = "/file/" + filename %}
2016-11-27 09:06:11 +00:00
2016-09-18 08:33:46 +00:00
<style>
#content_body
{
/* Override common.css */
flex-direction: row;
2016-09-18 08:33:46 +00:00
flex: 1;
}
#left
{
display: flex;
padding: 8px;
2016-09-18 08:33:46 +00:00
flex-direction: column;
justify-content: flex-start;
background-color: rgba(0, 0, 0, 0.1);
max-width: 300px;
2016-09-18 08:33:46 +00:00
}
#right
{
flex: 1;
display: flex;
}
@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;
flex-direction: row;
width: initial;
max-width: none;
margin-top: 8px;
}
#right
{
flex: none;
height: calc(100% - 20px);
}
2016-09-18 08:33:46 +00:00
}
#editor_area
{
flex: 3;
}
#message_area
{
overflow-y: auto;
flex: 1;
background-color: rgba(0, 0, 0, 0.1);
}
2016-11-07 02:00:30 +00:00
.photo_viewer
2016-09-18 08:33:46 +00:00
{
display: flex;
flex: 1;
flex-direction: column;
justify-content: center;
align-items: center;
}
2016-11-07 02:00:30 +00:00
.photo_viewer a
2016-09-18 08:33:46 +00:00
{
2016-10-30 01:46:23 +00:00
display: flex;
justify-content: center;
align-items: center;
}
#photo_img_holder
{
height: 100%;
width: 100%;
2016-09-18 08:33:46 +00:00
display: flex;
justify-content: center;
align-items: center;
2016-10-30 01:46:23 +00:00
background-repeat: no-repeat;
2016-09-18 08:33:46 +00:00
}
#photo_img_holder img
2016-09-18 08:33:46 +00:00
{
2016-10-10 03:50:13 +00:00
max-height: 100%;
max-width: 100%;
2016-09-18 08:33:46 +00:00
}
2016-11-07 02:00:30 +00:00
.photo_viewer audio
2016-09-18 08:33:46 +00:00
{
width: 100%;
}
2016-11-07 02:00:30 +00:00
.photo_viewer video
2016-09-18 08:33:46 +00:00
{
max-width: 100%;
max-height: 100%;
width: 100%;
}
</style>
2016-11-27 09:06:11 +00:00
</head>
2016-09-18 08:33:46 +00:00
<body>
{{header.make_header(session=session)}}
2016-09-18 08:33:46 +00:00
<div id="content_body">
<div id="left">
<div id="editor_area">
<!-- TAG INFO -->
<h4>Tags</h4>
<ul id="this_tags">
{% set tags = photo.sorted_tags() %}
{% for tag in tags %}
2016-09-18 08:33:46 +00:00
<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>
2016-09-18 08:33:46 +00:00
</li>
{% endfor %}
<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>
</ul>
<!-- METADATA & DOWNLOAD -->
<h4>File info</h4>
<ul id="metadata">
{% if photo.author_id %}
{% set author = photo.author() %}
<li>Author: <a href="/user/{{author.username}}">{{author.username}}</a>
2016-10-10 03:50:13 +00:00
{% endif %}
{% if photo.width %}
<li>Dimensions: {{photo.width}}x{{photo.height}} px</li>
<li>Aspect ratio: {{photo.ratio}}</li>
2016-09-18 08:33:46 +00:00
{% 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>
2016-09-18 08:33:46 +00:00
</ul>
<!-- CONTAINING ALBUMS -->
{% set albums = photo.albums() %}
{% if albums %}
2016-09-18 08:33:46 +00:00
<h4>Albums containing this photo</h4>
<ul id="containing albums">
{% for album in albums %}
<li><a href="/album/{{album.id}}">{{album.title}}</a></li>
2016-09-18 08:33:46 +00:00
{% endfor %}
{% endif %}
</ul>
</div>
<div id="message_area">
</div>
</div>
<div id="right">
2016-10-30 01:46:23 +00:00
<!-- THE PHOTO ITSELF -->
2016-11-07 02:00:30 +00:00
<div class="photo_viewer">
{% if photo.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.mimetype == "video" %}
<video src="{{link}}" controls preload=none {%if photo.thumbnail%}poster="/thumbnail/{{photo.id}}.jpg"{%endif%}></video>
{% elif photo.mimetype == "audio" %}
2016-09-18 08:33:46 +00:00
<audio src="{{link}}" controls></audio>
{% else %}
<a href="{{link}}">View {{filename}}</a>
{% endif %}
</div>
</div>
</div>
</body>
2016-11-27 09:06:11 +00:00
2016-09-18 08:33:46 +00:00
<script type="text/javascript">
var content_body = document.getElementById('content_body');
2016-10-10 03:50:13 +00:00
var add_tag_box = document.getElementById('add_tag_textbox');
var add_tag_button = document.getElementById('add_tag_button');
2016-09-18 08:33:46 +00:00
var message_area = document.getElementById('message_area');
2016-10-10 03:50:13 +00:00
add_tag_box.onkeydown = function(){entry_with_history_hook(add_tag_box, add_tag_button)};
2016-09-18 08:33:46 +00:00
function add_photo_tag(photoid, tagname, callback)
{
if (tagname === ""){return}
var url = "/photo/" + photoid;
data = new FormData();
data.append("add_tag", tagname);
return post(url, data, callback);
}
function remove_photo_tag(photoid, tagname, callback)
{
if (tagname === ""){return}
var url = "/photo/" + photoid;
data = new FormData();
data.append("remove_tag", 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 tagname = response["tagname"];
if ("error" in response)
{
message_positivity = "message_negative";
message_text = '"' + tagname + '" ' + response["error"];
}
else if ("action" in response)
{
var action = response["action"];
message_positivity = "message_positive";
if (action == "add_tag")
{
message_text = "Added tag " + tagname;
}
else if (action == "remove_tag")
{
message_text = "Removed tag " + tagname;
}
}
create_message_bubble(message_area, message_positivity, message_text, 8000);
}
2016-10-30 01:46:23 +00:00
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();
}
2016-10-30 01:46:23 +00:00
}
function toggle_hoverzoom()
{
img = document.getElementById("photo_img");
if (img.style.opacity === "0")
{
disable_hoverzoom();
}
else
{
enable_hoverzoom();
}
}
2016-11-27 09:06:11 +00:00
photo_img_holder = document.getElementById("photo_img_holder");
photo_img = document.getElementById("photo_img");
2016-10-30 01:46:23 +00:00
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.
2016-11-27 09:06:11 +00:00
var mouse_x = event.offsetX;
mouse_x -= (photo_img_holder.offsetWidth / 2);
mouse_x *= 1.05;
mouse_x += (photo_img_holder.offsetWidth / 2);
2016-11-27 09:06:11 +00:00
var mouse_y = event.offsetY;
mouse_y -= (photo_img_holder.offsetHeight / 2);
mouse_y *= 1.05;
mouse_y += (photo_img_holder.offsetHeight / 2);
2016-11-27 09:06:11 +00:00
if (photo_img.naturalWidth < photo_img_holder.offsetWidth)
2016-10-30 01:46:23 +00:00
{
// If the image is smaller than the frame, just center it
2016-11-27 09:06:11 +00:00
x = (photo_img.naturalWidth - photo_img_holder.offsetWidth) / 2;
2016-10-30 01:46:23 +00:00
}
else
{
// Take the amount of movement necessary (frame width - image width)
// times our distance across the image as a percentage.
2016-11-27 09:06:11 +00:00
x = (photo_img.naturalWidth - photo_img_holder.offsetWidth) * (mouse_x / photo_img_holder.offsetWidth);
2016-10-30 01:46:23 +00:00
}
2016-11-27 09:06:11 +00:00
if (photo_img.naturalHeight < photo_img_holder.offsetHeight)
2016-10-30 01:46:23 +00:00
{
2016-11-27 09:06:11 +00:00
y = (photo_img.naturalHeight - photo_img_holder.offsetHeight) / 2;
2016-10-30 01:46:23 +00:00
}
else
{
2016-11-27 09:06:11 +00:00
y = (photo_img.naturalHeight - photo_img_holder.offsetHeight) * (mouse_y / photo_img_holder.offsetHeight);
2016-10-30 01:46:23 +00:00
}
//console.log(x);
2016-11-27 09:06:11 +00:00
photo_img_holder.style.backgroundPosition=(-x)+"px "+(-y)+"px";
2016-10-30 01:46:23 +00:00
}
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
);
2016-11-27 09:06:11 +00:00
</script>
</html>