mirror of
https://github.com/netbox-community/netbox.git
synced 2026-02-22 08:47:46 +01:00
Closes #20211: Use thumbnails for ImageAttachment hover previews to improve page load performance (#21386)
This commit is contained in:
@@ -39,9 +39,20 @@ __all__ = (
|
||||
)
|
||||
|
||||
IMAGEATTACHMENT_IMAGE = """
|
||||
{% load thumbnail %}
|
||||
{% if record.image %}
|
||||
<a href="{{ record.image.url }}" target="_blank" class="image-preview" data-bs-placement="top">
|
||||
<i class="mdi mdi-image"></i></a>
|
||||
{% thumbnail record.image "400x400" as tn %}
|
||||
<a href="{{ record.get_absolute_url }}"
|
||||
class="image-preview"
|
||||
data-preview-url="{{ tn.url }}"
|
||||
data-bs-placement="left"
|
||||
title="{{ record.filename }}"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
aria-label="{{ record.filename }}">
|
||||
<i class="mdi mdi-image"></i>
|
||||
</a>
|
||||
{% endthumbnail %}
|
||||
{% endif %}
|
||||
<a href="{{ record.get_absolute_url }}">{{ record.filename|truncate_middle:16 }}</a>
|
||||
"""
|
||||
|
||||
2
netbox/project-static/dist/netbox.css
vendored
2
netbox/project-static/dist/netbox.css
vendored
File diff suppressed because one or more lines are too long
2
netbox/project-static/dist/netbox.js
vendored
2
netbox/project-static/dist/netbox.js
vendored
File diff suppressed because one or more lines are too long
6
netbox/project-static/dist/netbox.js.map
vendored
6
netbox/project-static/dist/netbox.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -150,20 +150,22 @@ function initSidebarAccordions(): void {
|
||||
*/
|
||||
function initImagePreview(): void {
|
||||
for (const element of getElements<HTMLAnchorElement>('a.image-preview')) {
|
||||
// Generate a max-width that's a quarter of the screen's width (note - the actual element
|
||||
// width will be slightly larger due to the popover body's padding).
|
||||
const maxWidth = `${Math.round(window.innerWidth / 4)}px`;
|
||||
// Prefer a thumbnail URL for the popover (so we don't preload full-size images),
|
||||
// but fall back to the link target if no thumbnail was provided.
|
||||
const previewUrl = element.dataset.previewUrl ?? element.href;
|
||||
const image = createElement('img', { src: previewUrl });
|
||||
|
||||
// Create an image element that uses the linked image as its `src`.
|
||||
const image = createElement('img', { src: element.href });
|
||||
image.style.maxWidth = maxWidth;
|
||||
// Ensure lazy loading and async decoding
|
||||
image.loading = 'lazy';
|
||||
image.decoding = 'async';
|
||||
|
||||
// Create a container for the image.
|
||||
const content = createElement('div', null, null, [image]);
|
||||
|
||||
// Initialize the Bootstrap Popper instance.
|
||||
new Popover(element, {
|
||||
// Attach this custom class to the popover so that it styling can be controlled via CSS.
|
||||
// Attach this custom class to the popover so that its styling
|
||||
// can be controlled via CSS.
|
||||
customClass: 'image-preview-popover',
|
||||
trigger: 'hover',
|
||||
html: true,
|
||||
|
||||
@@ -89,6 +89,29 @@ img.plugin-icon {
|
||||
}
|
||||
}
|
||||
|
||||
// Image preview popover (rendered for <a.image-preview> by initImagePreview())
|
||||
.image-preview-popover {
|
||||
--bs-popover-max-width: clamp(240px, 25vw, 640px);
|
||||
|
||||
.popover-header {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.popover-body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
img {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
max-height: clamp(160px, 33vh, 640px);
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
body[data-bs-theme=dark] {
|
||||
// Assuming icon is black/white line art, invert it and tone down brightness
|
||||
img.plugin-icon {
|
||||
|
||||
Reference in New Issue
Block a user