philomena/assets/js/resizablemedia.js

73 lines
3.1 KiB
JavaScript
Raw Normal View History

2019-10-05 02:09:52 +02:00
let mediaContainers;
/* Hardcoded dimensions of thumb boxes; at mediaLargeMinSize, large box becomes a small one (font size gets diminished).
* At minimum width, the large box still has four digit fave/score numbers and five digit comment number fitting in a single row
* (small box may lose the number of comments in a hidden overflow) */
2024-07-04 02:27:59 +02:00
const mediaLargeMaxSize = 250,
mediaLargeMinSize = 190,
mediaSmallMaxSize = 156,
mediaSmallMinSize = 140;
2019-10-05 02:09:52 +02:00
/* Margin between thumbs (6) + borders (2) + 1 extra px to correct rounding errors */
const mediaBoxOffset = 9;
export function processResizableMedia() {
[].slice.call(mediaContainers).forEach(container => {
const containerHasLargeBoxes = container.querySelector('.media-box__content--large') !== null,
2024-07-04 02:27:59 +02:00
containerWidth = container.offsetWidth - 14; /* subtract container padding */
2019-10-05 02:09:52 +02:00
/* If at least three large boxes fit in a single row, we do not downsize them to small ones.
* This ensures that desktop users get less boxes in a row, but with bigger images inside. */
const largeBoxesFitting = Math.floor(containerWidth / (mediaLargeMinSize + mediaBoxOffset));
if (largeBoxesFitting >= 3) {
/* At the same time, we don't want small boxes to be upscaled. */
if (containerHasLargeBoxes) {
/* Larger boxes are preferred to more items in a row */
setMediaSize(container, containerWidth, mediaLargeMinSize, mediaLargeMaxSize);
}
2024-07-04 02:27:59 +02:00
} else {
/* Mobile users, on the other hand, should get as many boxes in a row as possible */
2019-10-05 02:09:52 +02:00
setMediaSize(container, containerWidth, mediaSmallMinSize, mediaSmallMaxSize);
}
});
}
function applyMediaSize(container, size) {
const mediaItems = container.querySelectorAll('.media-box__content');
[].slice.call(mediaItems).forEach(item => {
item.style.width = `${size}px`;
item.style.height = `${size}px`;
2019-11-15 16:32:26 +01:00
const header = item.parentNode.firstElementChild;
2019-10-05 02:09:52 +02:00
// TODO: Make this proper and/or rethink this entire croc of bullshit
item.parentNode.style.width = `${size}px`;
/* When the large box has width less than mediaLargeMinSize, the header gets wrapped and occupies more than one line.
* To prevent that, we add a class that diminishes its padding and font size. */
if (size < mediaLargeMinSize) {
header.classList.add('media-box__header--small');
2024-07-04 02:27:59 +02:00
} else {
2019-10-05 02:09:52 +02:00
header.classList.remove('media-box__header--small');
}
});
}
function setMediaSize(container, containerWidth, minMediaSize, maxMediaSize) {
const maxThumbsFitting = Math.floor(containerWidth / (minMediaSize + mediaBoxOffset)),
2024-07-04 02:27:59 +02:00
minThumbsFitting = Math.floor(containerWidth / (maxMediaSize + mediaBoxOffset)),
fitThumbs = Math.round((maxThumbsFitting + minThumbsFitting) / 2),
thumbSize = Math.max(Math.floor(containerWidth / fitThumbs) - 9, minMediaSize);
2019-10-05 02:09:52 +02:00
applyMediaSize(container, thumbSize);
}
function initializeListener() {
mediaContainers = document.querySelectorAll('.js-resizable-media-container');
if (mediaContainers.length > 0) {
window.addEventListener('resize', processResizableMedia);
processResizableMedia();
}
}
export { initializeListener };