From 1914fd42f9b150c07a898a808e3a538231dba387 Mon Sep 17 00:00:00 2001 From: Terranom674 Date: Sun, 16 Aug 2026 13:01:00 +0200 Subject: [PATCH] Make public photo selection independent of gdThumb --- js/public_selection.js | 99 +++++++++++++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 20 deletions(-) diff --git a/js/public_selection.js b/js/public_selection.js index 5d97332..b7045fd 100644 --- a/js/public_selection.js +++ b/js/public_selection.js @@ -4,20 +4,69 @@ var active = false; var selected = {}; - function getThumbs() { - return $('#thumbnails .gdthumb'); + function candidateLinks() { + return $('#thumbnails a[href], .thumbnails a[href]'); } - function imageIdFromThumb($thumb) { - var $link = $thumb.find('a[href]').first(); - var href = $link.attr('href') || ''; - var matches = href.match(/(?:image|picture)\/(\d+)|[?&](?:image_id|id)=(\d+)/i); - if (matches) { - return parseInt(matches[1] || matches[2], 10); + function imageIdFromHref(href) { + if (!href) { + return 0; } - var id = $thumb.data('image-id') || $thumb.attr('data-image-id'); - return id ? parseInt(id, 10) : 0; + var patterns = [ + /(?:^|\/)picture(?:\.php)?\?\/(\d+)(?:[-/]|$)/i, + /(?:^|\/)picture\/(\d+)(?:[-/]|$)/i, + /(?:^|\/)image\/(\d+)(?:[-/]|$)/i, + /[?&](?:image_id|image|picture_id|id)=(\d+)(?:&|$)/i + ]; + + for (var i = 0; i < patterns.length; i++) { + var match = href.match(patterns[i]); + if (match) { + return parseInt(match[1], 10) || 0; + } + } + + return 0; + } + + function imageIdFromLink($link) { + var direct = $link.attr('data-image-id') || $link.data('image-id'); + if (direct) { + return parseInt(direct, 10) || 0; + } + + var $withId = $link.closest('[data-image-id]'); + if ($withId.length) { + return parseInt($withId.attr('data-image-id'), 10) || 0; + } + + return imageIdFromHref($link.attr('href') || ''); + } + + function itemFromLink($link) { + // Prefer semantic list/card wrappers used by Piwigo themes and thumbnail + // plugins. gdThumb is only one supported markup, not a dependency. + var $item = $link.closest('li, .thumbnail, .thumbnailCategory, .gdthumb, .card'); + return $item.length ? $item.first() : $link; + } + + function selectableLinks() { + return candidateLinks().filter(function () { + return imageIdFromLink($(this)) > 0; + }); + } + + function refreshSelectableItems() { + selectableLinks().each(function () { + var $link = $(this); + var imageId = imageIdFromLink($link); + var $item = itemFromLink($link); + $item.addClass('bratonien-selectable').attr('data-bratonien-image-id', imageId); + if (selected[imageId]) { + $item.addClass('bratonien-selected'); + } + }); } function updateBar() { @@ -31,6 +80,7 @@ $('body').toggleClass('bratonien-selection-active', active); $('#bratonien-selection-bar').prop('hidden', !active); $('#bratonien-selection-toggle').toggleClass('active', active); + refreshSelectableItems(); if (!active) { clearSelection(); } @@ -38,7 +88,7 @@ function clearSelection() { selected = {}; - getThumbs().removeClass('bratonien-selected'); + $('.bratonien-selectable').removeClass('bratonien-selected'); updateBar(); } @@ -47,26 +97,27 @@ setActive(!active); }); - $(document).on('click', '#thumbnails .gdthumb a', function (e) { + $(document).on('click', '#thumbnails a[href], .thumbnails a[href]', function (e) { if (!active) { return; } + var $link = $(this); + var imageId = imageIdFromLink($link); + if (!imageId) { + return; + } + e.preventDefault(); e.stopPropagation(); - var $thumb = $(this).closest('.gdthumb'); - var imageId = imageIdFromThumb($thumb); - if (!imageId) { - return; - } - + var $item = itemFromLink($link); if (selected[imageId]) { delete selected[imageId]; - $thumb.removeClass('bratonien-selected'); + $item.removeClass('bratonien-selected'); } else { selected[imageId] = true; - $thumb.addClass('bratonien-selected'); + $item.addClass('bratonien-selected'); } updateBar(); }); @@ -84,4 +135,12 @@ var separator = window.BratonienSelectionConfig.downloadUrl.indexOf('?') === -1 ? '?' : '&'; window.location.href = window.BratonienSelectionConfig.downloadUrl + separator + 'bratonien_selection=' + encodeURIComponent(ids.join(',')); }); + + // Some plugins append thumbnails after the initial page render. Refresh the + // markers without depending on any particular thumbnail implementation. + $(document).ajaxComplete(function () { + if (active) { + refreshSelectableItems(); + } + }); })(jQuery);