Add overlay lightbox for displaying inline image previews.

This adds an event listener (by way of delegation) to the
.message_inline_image elements that pops up the overlay and hides it
when the overlay exit is clicked.

Fixes #654.
This commit is contained in:
Brock Whittaker 2016-09-21 17:05:24 -07:00 committed by Tim Abbott
parent 2ea7d2341e
commit 87afe61860
9 changed files with 191 additions and 1 deletions

View File

@ -368,6 +368,25 @@ $(function () {
.text("Bringing you to your latest messages…"));
});
(function () {
$("#main_div").on("click", ".message_inline_image a", function (e) {
var img = e.target,
row = rows.id($(img).closest(".message_row")),
user = current_msg_list.get(row).sender_full_name;
// prevent the link from opening in a new page.
e.preventDefault();
// prevent the message compose dialog from happening.
e.stopPropagation();
ui.lightbox_photo(img, user);
});
$("#overlay .exit").click(function (e) {
ui.exit_lightbox_photo();
});
}());
// MAIN CLICK HANDLER
$(document).on('click', function (e) {

View File

@ -246,6 +246,10 @@ function process_hotkey(e) {
}
}
if (event_name === "escape" && $("#overlay").hasClass("show")) {
ui.exit_lightbox_photo();
}
// If we're on a button or a link and have pressed enter, let the
// browser handle the keypress
//
@ -361,7 +365,8 @@ function process_hotkey(e) {
$(document).keydown(function (e) {
// Restrict to non-alphanumeric keys
if (48 > e.which || 90 < e.which) {
// check if 27 (esc) because it doesn't register under .keypress()
if (48 > e.which || 90 < e.which || e.which === 27) {
if (process_hotkey(e)) {
e.preventDefault();
}

View File

@ -281,6 +281,29 @@ exports.small_avatar_url = function (message) {
}
};
exports.lightbox_photo = function (image, user) {
// image should be an Image Object in JavaScript.
var url = $(image).attr("src"),
title = $(image).parent().attr("title");
$("#overlay .image-preview")
.css("background-image", "url(" + url + ")");
$("#overlay").addClass("show");
$(".right-sidebar, .column-middle-inner, .left-sidebar").addClass("visual-blur");
$(".title").text(title || "N/A");
$(".user").text(user);
$(".image-actions .open, .image-actions .download").attr("href", url);
};
exports.exit_lightbox_photo = function (image) {
$("#overlay").removeClass("show");
$(".right-sidebar, .column-middle-inner, .left-sidebar").removeClass("visual-blur");
};
var loading_more_messages_indicator_showing = false;
exports.show_loading_more_messages_indicator = function () {
if (! loading_more_messages_indicator_showing) {

116
static/styles/overlay.css Normal file
View File

@ -0,0 +1,116 @@
#overlay {
position: fixed;
top: 0px;
left: 0px;
width: 100vw;
height: 100vh;
pointer-events: none;
opacity: 0;
background-color: rgba(255,255,255,0.4);
box-shadow: 0 0 20px rgba(0,0,0,0.2);
z-index: 101;
transition: all 0.2s ease;
}
#overlay.show {
pointer-events: auto;
opacity: 1;
}
#overlay .image-preview {
position: relative;
width: 100%;
height: calc(100% - 80px);
background-color: #19203a;
box-shadow: 0 0 20px rgba(0,0,0,0.2);
background-size: contain;
background-repeat: no-repeat;
background-position: center center;
}
#overlay .image-preview .exit {
position: absolute;
top: 20px;
right: 20px;
color: rgba(255,255,255,0.8);
font-size: 2rem;
font-weight: 200;
opacity: 0;
pointer-events: none;
cursor: pointer;
transition: all 0.2s ease;
}
#overlay .image-preview:hover .exit {
pointer-events: auto;
opacity: 1;
}
#overlay .image-description,
#overlay .image-actions {
float: left;
margin: 10px 20px;
}
#overlay .image-actions {
float: right;
}
#overlay .image-actions .icon {
font-size: 1.1rem;
display: inline-block;
margin-top: 5px;
}
#overlay .image-actions .icon .text {
font-size: 0.9rem;
margin-right: 5px;
}
#overlay .image-actions span:nth-of-type(2) {
position: relative;
top: 1px;
}
#overlay .image-actions .open span:nth-of-type(2) {
top: 2px;
}
#overlay .image-description {
/* approx width of screen minus action buttons on the side. */
width: calc(100% - 290px);
}
#overlay .image-description .title {
font-size: 2rem;
font-weight: 300;
line-height: normal;
max-width: calc(100%);
/* Required for text-overflow */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#overlay .image-description .user {
font-size: 0.8rem;
font-weight: 600;
color: #888;
}
.image-actions a.button {
text-decoration: none;
}
.button .download {
top: 1px;
}

View File

@ -26,6 +26,12 @@ body,
transition: background-color 200ms linear;
}
.visual-blur {
filter: blur(15px);
-moz-filter: blur(15px);
-webkit-filter: blur(15px);
}
input,
button,
select,

View File

@ -0,0 +1,17 @@
<div id="overlay">
<div class="image-preview">
<div class="exit">x</div>
</div>
<div class="image-description">
<div class="title"></div>
<div class="user"></div>
</div>
<div class="image-actions">
<a class="button sea-green small-flex open icon" target="_blank">
<span class="text">Open</span> <span class="icon-vector-external-link"></span>
</a>
<a class="button sea-green small-flex download icon" download>
<span class="text">Download</span> <span class="icon-vector-download"></span>
</a>
</div>
</div>

View File

@ -119,6 +119,7 @@ var page_params = {{ page_params }};
<div class="column-right">
{% include "zerver/right-sidebar.html" %}
</div><!--/right sidebar-->
{% include "zerver/image-overlay.html" %}
</div><!--/row-->
{% include "zerver/keyboard_shortcuts.html" %}
{% include "zerver/search_operators.html" %}

View File

@ -15,6 +15,7 @@ GENERIC_KEYWORDS = [
'error',
'expanded',
'hide',
'show',
'notdisplayed',
'popover',
'success',

View File

@ -650,6 +650,7 @@ PIPELINE = {
'styles/zulip.css',
'styles/media.css',
'styles/settings.css',
'styles/overlay.css',
'styles/pygments.css',
'styles/thirdparty-fonts.css',
# We don't want fonts.css on QtWebKit, so its omitted here
@ -665,6 +666,7 @@ PIPELINE = {
'styles/zulip.css',
'styles/media.css',
'styles/settings.css',
'styles/overlay.css',
'styles/pygments.css',
'styles/thirdparty-fonts.css',
'styles/fonts.css',