Flatten lightbox comment into a vue component
Deploy Livetrail / deploy (push) Successful in 18s

This commit is contained in:
2026-09-09 17:27:19 +02:00
parent e2a694ba03
commit dc4480c4e2
5 changed files with 79 additions and 60 deletions
+54 -9
View File
@@ -1,24 +1,26 @@
<script>
import AppIcon from '@components/AppIcon';
import ProjectRelTime from '@components/ProjectRelTime';
import { getStyleProperty } from '@scripts/common';
/* lightbox (https://github.com/lokesh/lightbox2) converted to a vue component and improved to support videos */
export default {
components: {
AppIcon
AppIcon,
ProjectRelTime
},
props: {
alwaysShowNavOnTouchDevices: {type: Boolean, default: false},
positionFromTop: {type: Number, default: 50},
wrapAround: {type: Boolean, default: false},
disableScrolling: {type: Boolean, default: false},
sanitizeTitle: {type: Boolean, default: false},
hasVideo: {type: Boolean, default: true},
maxWidth: {type: Number, default: null},
maxHeight: {type: Number, default: null}
},
emits: ['media-change', 'closing'],
inject: ['isMobile'],
data() {
/*
fadeDuration/imageFadeDuration/resizeDuration read --trans-quick/--trans-slow
@@ -44,6 +46,33 @@ export default {
resizeDuration
};
},
computed: {
currentMedia() {
return this.album[this.currentImageIndex] || null;
},
relTimeLines() {
const media = this.currentMedia;
if(!media || this.isMobile()) return [];
const postedOn = {
key: 'posted',
icon: 'upload',
titleWrapperLangId: 'media.posted_on',
localTime: media.postedOnLocalTime,
siteTime: media.postedOnSiteTime,
offset: media.postedOnDayOffset
};
const takenOn = {
key: 'taken',
icon: media.type+'-shot',
titleWrapperLangId: 'media.'+media.type+'_taken_on',
localTime: media.takenOnLocalTime,
siteTime: media.takenOnSiteTime,
offset: media.takenOnDayOffset
};
return (media.context == 'marker') ? [takenOn, postedOn] : [postedOn, takenOn];
}
},
mounted() {
this.setVisible(this.$refs.overlay, false);
this.setVisible(this.$refs.lightboxEl, false);
@@ -122,12 +151,19 @@ export default {
this.album.push({
alt: link.getAttribute('data-alt') || '',
link: link.getAttribute('href'),
title: link.getAttribute('data-title') || link.getAttribute('title') || '',
orientation: parseInt(link.getAttribute('data-orientation') || '0', 10),
type: link.getAttribute('data-type') || 'image',
id: link.getAttribute('data-id'),
width: parseInt(img?.getAttribute('width') || '0', 10),
height: parseInt(img?.getAttribute('height') || '0', 10),
context: link.getAttribute('data-context') || '',
comment: link.getAttribute('data-comment') || '',
postedOnLocalTime: link.getAttribute('data-posted-on-local-time') || '',
postedOnSiteTime: link.getAttribute('data-posted-on-site-time') || '',
postedOnDayOffset: link.getAttribute('data-posted-on-day-offset') || '',
takenOnLocalTime: link.getAttribute('data-taken-on-local-time') || '',
takenOnSiteTime: link.getAttribute('data-taken-on-site-time') || '',
takenOnDayOffset: link.getAttribute('data-taken-on-day-offset') || '',
set: link.getAttribute('data-lightbox') || ''
});
},
@@ -346,16 +382,16 @@ export default {
this.$refs.next.style.opacity = '';
}
},
hasCaption(media) {
return !!(media && (media.comment || media.postedOnSiteTime || media.takenOnSiteTime));
},
updateDetails(media = this.album[this.currentImageIndex], show = true) {
if(!media) return;
if(media.title) {
if(this.sanitizeTitle) this.$refs.caption.textContent = media.title;
else this.$refs.caption.innerHTML = media.title;
if(this.hasCaption(media)) {
if(show) this.fade(this.$refs.caption, true, 200);
else this.setVisible(this.$refs.caption, true);
} else {
this.$refs.caption.textContent = '';
this.setVisible(this.$refs.caption, false);
}
@@ -567,10 +603,19 @@ export default {
</a>
</div>
</div>
<div class="lb-dataContainer desktop" ref="dataContainer" @click="end()">
<div class="lb-dataContainer" ref="dataContainer" @click="end()">
<div class="lb-data">
<div class="lb-details">
<span class="lb-caption" ref="caption"></span>
<span class="lb-caption" ref="caption">
<template v-if="hasCaption(currentMedia)">
<span v-if="!!currentMedia?.comment" class="lb-caption-line comment">
<AppIcon icon="post" width="fixed" size="lg" text-classes="comment-text" :text="currentMedia.comment" />
</span>
<span v-for="line in relTimeLines" :key="line.key" class="lb-caption-line">
<ProjectRelTime :icon="line.icon" :titleWrapperLangId="line.titleWrapperLangId" :localTime="line.localTime" :siteTime="line.siteTime" :offset="line.offset" />
</span>
</template>
</span>
</div>
<div class="lb-closeContainer">
<a class="lb-close" ref="closeButton" href="#" role="button" @click.prevent.stop="end()" @keyup="onCloseKeyup">
+9 -39
View File
@@ -1,12 +1,10 @@
<script>
import appIcon from '@components/AppIcon';
import projectRelTime from '@components/ProjectRelTime';
import projectMapLink from '@components/ProjectMapLink';
export default {
components: {
appIcon,
projectRelTime,
projectMapLink
},
props: {
@@ -14,19 +12,7 @@ export default {
type: String
},
emits: ['opening-lightbox'],
data() {
return {
title:''
};
},
inject: ['lang', 'isMobile'],
mounted() {
this.title =
(this.$refs.comment?this.$refs.comment.outerHTML:'') +
this.$refs[this.type=='marker'?'takenon':'postedon'].outerHTML +
this.$refs[this.type=='marker'?'postedon':'takenon'].outerHTML
;
},
methods: {
openMedia() {
this.$refs.link.click();
@@ -42,12 +28,19 @@ export default {
:data-lightbox="type+'-medias'"
:data-type="options.subtype"
:data-id="options.id_media"
:data-title="title"
:data-orientation="options.rotate"
:data-context="type"
:data-comment="options.comment"
:data-posted-on-local-time="options.posted_on_formatted_time_local"
:data-posted-on-site-time="options.posted_on_formatted_time"
:data-posted-on-day-offset="options.posted_on_day_offset"
:data-taken-on-local-time="options.taken_on_formatted_time_local"
:data-taken-on-site-time="options.taken_on_formatted_time"
:data-taken-on-day-offset="options.taken_on_day_offset"
@click="$emit('opening-lightbox', $event)"
ref="link"
>
<img
<img
:src="options.thumb_path"
:width="options.width"
:height="options.height"
@@ -65,27 +58,4 @@ export default {
</p>
</div>
</a>
<div style="display:none">
<span v-if="options.comment" ref="comment" class="lb-caption-line comment desktop">
<appIcon icon="post" width="fixed" size="lg" text-classes="comment-text" :text="options.comment" />
</span>
<span ref="postedon" class="lb-caption-line">
<projectRelTime
icon="upload"
titleWrapperLangId="media.posted_on"
:localTime="options.posted_on_formatted_time_local"
:siteTime="options.posted_on_formatted_time"
:offset="options.posted_on_day_offset"
/>
</span>
<span ref="takenon" class="lb-caption-line">
<projectRelTime
:icon="options.subtype+'-shot'"
:titleWrapperLangId="'media.'+options.subtype+'_taken_on'"
:localTime="options.taken_on_formatted_time_local"
:siteTime="options.taken_on_formatted_time"
:offset="options.taken_on_day_offset"
/>
</span>
</div>
</template>
+7 -8
View File
@@ -41,7 +41,8 @@
postMessage: '',
quote: null,
sending: false,
focusZoomLevel: 15
focusZoomLevel: 15,
panAnimDuration: 500 //ms
};
},
inject: ['api', 'lang', 'project', 'feed', 'user', 'map', 'hash', 'consts', 'isMobile', 'getAnchor'],
@@ -156,15 +157,13 @@
this.anchorIcon = 'link';
}, 5000);
},
panMapToMarker(iAnimDuration=500) {
if(typeof iAnimDuration !== 'number') iAnimDuration = 500; //panMapToMarker will provide event on direct call in vue template
panMapToMarker(bCloseFeed=false) {
this.popupRequested = true;
if(this.isMobile()) this.feed.toggle(false);
if(bCloseFeed===true) this.feed.toggle(false);
this.hash.items = [this.project.project.codename, this.options.type, this.options.id];
return this.map.panToBetweenPanels(this.relatedMarkerLatLng, this.focusZoomLevel, iAnimDuration).then(() => {
return this.map.panToBetweenPanels(this.relatedMarkerLatLng, this.focusZoomLevel, this.panAnimDuration).then(() => {
this.openMarkerPopup();
});
},
@@ -238,7 +237,7 @@
<a v-if="replyVisible" class="reply clickable" @click="reply" :title="replyTitle">
<appIcon :icon="'reply'" />
</a>
<a v-if="anchorVisible" class="link desktop" @click="copyAnchor" ref="anchor" :href="anchorLink" :title="anchorTitle">
<a v-if="anchorVisible && !isMobile()" class="link" @click="copyAnchor" ref="anchor" :href="anchorLink" :title="anchorTitle">
<appIcon :icon="anchorIcon" />
</a>
</div>
@@ -251,7 +250,7 @@
</div>
<div class="body">
<div v-if="options.type == 'message'" class="body-box">
<div class="drill" @click.prevent="panMapToMarker" @pointerenter="onMouseEnter" @pointerleave="onMouseLeave">
<div class="drill" @click.prevent="()=>{panMapToMarker(isMobile());}" @pointerenter="onMouseEnter" @pointerleave="onMouseLeave">
<span v-if="options.weather_icon && options.weather_icon!='unknown'" class="weather clickable" :title="lang.get('weather.'+options.weather_icon)">
<appIcon :icon="options.weather_icon" :text="Math.round(options.weather_temp)+'°C'" text-classes="temperature" />
</span>
+9
View File
@@ -58,6 +58,15 @@ body.lb-disable-scrolling {
.lb-caption-line.comment {
flex: 1 1 auto;
min-width: 0;
.app-icon-with-text {
display: flex;
min-width: 0;
}
.comment-text {
@include common.no-text-overflow();
}
}
}
-4
View File
@@ -10,10 +10,6 @@
--button-width: 51px;
}
.desktop {
display: none !important;
}
.projects {
.panel-control-elem {
font-size: 2em;