add lightbox for post image previews 2
This commit is contained in:
@@ -172,7 +172,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="post-content">
|
<div class="post-content" data-r="collectImages">
|
||||||
<div class="plank even minimal secondary-bg no-shadow post-info">
|
<div class="plank even minimal secondary-bg no-shadow post-info">
|
||||||
<span>
|
<span>
|
||||||
{%- if tb_pretext -%}
|
{%- if tb_pretext -%}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
{%- block title -%}{{thread.title}}{%- endblock -%}
|
{%- block title -%}{{thread.title}}{%- endblock -%}
|
||||||
{%- block content -%}
|
{%- block content -%}
|
||||||
<bitty-8 data-connect="/static/js/bits/bookmark-menu.js"></bitty-8>
|
<bitty-8 data-connect="/static/js/bits/bookmark-menu.js"></bitty-8>
|
||||||
|
<bitty-8 data-connect="/static/js/bits/thread.js"></bitty-8>
|
||||||
{%- set td -%}
|
{%- set td -%}
|
||||||
<ul class="horizontal">
|
<ul class="horizontal">
|
||||||
<li>Started by <a href="{{url_for('users.user_page', username=started_by.username)}}">{{started_by.get_readable_name()}}</a> in topic <a href="{{url_for('topics.topic_by_id', topic_id=topic.id)}}">{{topic.name}}</a></li>
|
<li>Started by <a href="{{url_for('users.user_page', username=started_by.username)}}">{{started_by.get_readable_name()}}</a> in topic <a href="{{url_for('topics.topic_by_id', topic_id=topic.id)}}">{{topic.name}}</a></li>
|
||||||
@@ -84,6 +85,18 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{{ bookmark_menu() }}
|
{{ bookmark_menu() }}
|
||||||
|
<dialog closedby="any" class="plank thread-lighbox" data-r="showLightbox closeLightbox">
|
||||||
|
<div class="menu">
|
||||||
|
<button data-s="closeLightbox">Close</button>
|
||||||
|
<a href="" target="_blank" rel="noreferrer noopener" class="linkbutton alt">Open original</a>
|
||||||
|
</div>
|
||||||
|
<img class="lightbox-image" src="https://placehold.co/900x710">
|
||||||
|
<div class="menu">
|
||||||
|
<button data-s="lightboxPrevious">Previous</button>
|
||||||
|
<span data-r="lightboxSetCounter">0/0</span>
|
||||||
|
<button data-s="lightboxNext">Next</button>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
{%- if is_logged_in() and get_active_user().can_post_to_thread_or_topic(thread) -%}
|
{%- if is_logged_in() and get_active_user().can_post_to_thread_or_topic(thread) -%}
|
||||||
<form action="{{url_for('threads.reply', thread_id=thread.id)}}" method="POST" class="plank post-edit-form" data-listen="submit" data-r="clearThreadDraft" data-s="clearThreadDraft">
|
<form action="{{url_for('threads.reply', thread_id=thread.id)}}" method="POST" class="plank post-edit-form" data-listen="submit" data-r="clearThreadDraft" data-s="clearThreadDraft">
|
||||||
<h2 class="info">Reply to "{{thread.title}}"</h2>
|
<h2 class="info">Reply to "{{thread.title}}"</h2>
|
||||||
|
|||||||
@@ -743,6 +743,125 @@ table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ol.sortable-list {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--base-padding);
|
||||||
|
flex-direction: column;
|
||||||
|
list-style: none;
|
||||||
|
flex-grow: 1;
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--big-padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
li.immovable .dragger {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.plank.dragger {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
/*background-color: var(--bg-color-tertiary);*/
|
||||||
|
padding: var(--base-padding);
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sortable-item-inner {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--base-padding);
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.row {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.row):not(.full) > * {
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-editor-badge-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: var(--base-padding);
|
||||||
|
|
||||||
|
& > input[type=text], & > input[type=url] {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-editor-file-picker {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--base-padding);
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
min-width: 150px;
|
||||||
|
|
||||||
|
& > input[type=file] {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&::file-selector-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-editor-badge-select {
|
||||||
|
display: flex;
|
||||||
|
gap: var(--base-padding);
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
min-width: 200px;
|
||||||
|
& > select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.js-only {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.plank.thread-lighbox {
|
||||||
|
margin: auto;
|
||||||
|
min-width: 80vw;
|
||||||
|
min-height: 70vh;
|
||||||
|
max-width: 80vw;
|
||||||
|
max-height: 70vh;
|
||||||
|
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
& > .menu {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:open {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightbox-image {
|
||||||
|
max-width: 50vw;
|
||||||
|
max-height: 50vh;
|
||||||
|
}
|
||||||
|
|
||||||
/* babycode tags */
|
/* babycode tags */
|
||||||
.inline-code {
|
.inline-code {
|
||||||
background-color: var(--code-bg-color);
|
background-color: var(--code-bg-color);
|
||||||
@@ -924,97 +1043,6 @@ a.mention {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ol.sortable-list {
|
|
||||||
display: flex;
|
|
||||||
gap: var(--base-padding);
|
|
||||||
flex-direction: column;
|
|
||||||
list-style: none;
|
|
||||||
flex-grow: 1;
|
|
||||||
margin: 0;
|
|
||||||
padding-left: 0;
|
|
||||||
|
|
||||||
li {
|
|
||||||
display: flex;
|
|
||||||
gap: var(--big-padding);
|
|
||||||
}
|
|
||||||
|
|
||||||
li.immovable .dragger {
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.plank.dragger {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
/*background-color: var(--bg-color-tertiary);*/
|
|
||||||
padding: var(--base-padding);
|
|
||||||
cursor: move;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sortable-item-inner {
|
|
||||||
display: flex;
|
|
||||||
gap: var(--base-padding);
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
& > * {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.row {
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(.row):not(.full) > * {
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-editor-badge-container {
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
gap: var(--base-padding);
|
|
||||||
|
|
||||||
& > input[type=text], & > input[type=url] {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-editor-file-picker {
|
|
||||||
display: flex;
|
|
||||||
gap: var(--base-padding);
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
min-width: 150px;
|
|
||||||
|
|
||||||
& > input[type=file] {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&::file-selector-button {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.badge-editor-badge-select {
|
|
||||||
display: flex;
|
|
||||||
gap: var(--base-padding);
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
min-width: 200px;
|
|
||||||
& > select {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.js-only {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
body {
|
body {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
@@ -1085,4 +1113,17 @@ ol.sortable-list {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dialog.plank.thread-lighbox {
|
||||||
|
margin: 0;
|
||||||
|
min-width: 100vw;
|
||||||
|
min-height: 100vh;
|
||||||
|
max-width: unset;
|
||||||
|
max-height: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightbox-image {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
64
data/static/js/bits/thread.js
Normal file
64
data/static/js/bits/thread.js
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
export const b = {
|
||||||
|
init: 'activatePostImages',
|
||||||
|
}
|
||||||
|
|
||||||
|
const POST_IMAGES_SELECTOR = 'img.post-image:not(aside img.post-image)'
|
||||||
|
|
||||||
|
let images = [];
|
||||||
|
let currentIndex = 0;
|
||||||
|
|
||||||
|
export function activatePostImages(_, __, ___) {
|
||||||
|
const images = document.querySelectorAll(POST_IMAGES_SELECTOR);
|
||||||
|
images.forEach(image => {
|
||||||
|
image.style.cursor = 'pointer';
|
||||||
|
image.dataset.s = 'collectImages';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function collectImages(_, sender, el) {
|
||||||
|
if (!el.contains(sender)) return;
|
||||||
|
images = Array.from(el.querySelectorAll(POST_IMAGES_SELECTOR));
|
||||||
|
currentIndex = images.indexOf(sender);
|
||||||
|
b.trigger('showLightbox');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function showLightbox(_, __, el) {
|
||||||
|
const originalImg = images[currentIndex];
|
||||||
|
const lightboxImg = el.querySelector('img');
|
||||||
|
const anchor = el.querySelector('a');
|
||||||
|
anchor.href = originalImg.src;
|
||||||
|
lightboxImg.src = originalImg.src;
|
||||||
|
lightboxImg.alt = originalImg.alt;
|
||||||
|
|
||||||
|
if (!el.open) {
|
||||||
|
el.showModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
b.trigger('lightboxSetCounter');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function closeLightbox(_, __, el) {
|
||||||
|
el.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function lightboxSetCounter(_, __, el) {
|
||||||
|
el.innerText = `${currentIndex + 1}/${images.length}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function lightboxNext(_, __, ___) {
|
||||||
|
if (images.length == 1) return;
|
||||||
|
currentIndex++;
|
||||||
|
if (currentIndex >= images.length) {
|
||||||
|
currentIndex = 0;
|
||||||
|
}
|
||||||
|
b.trigger('showLightbox');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function lightboxPrevious(_, __, ___) {
|
||||||
|
if (images.length == 1) return;
|
||||||
|
currentIndex--;
|
||||||
|
if (currentIndex < 0) {
|
||||||
|
currentIndex = images.length - 1;
|
||||||
|
}
|
||||||
|
b.trigger('showLightbox');
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user