diff options
| author | Roger Rehnelt <noreply@maennchen1.de> | 2026-10-03 17:56:56 +0200 |
|---|---|---|
| committer | Roger Rehnelt <noreply@maennchen1.de> | 2026-10-03 17:56:56 +0200 |
| commit | c5a04225526941059a15dc7e7af362882a07942c (patch) | |
| tree | 482abdf6e0b43fc1039b18badd0efdcb2f0100ea | |
| parent | 5c4bd30cf46b1bdbfdaed50c5d534bb8bfa1e143 (diff) | |
Produktfilter: filtert die Produktkacheln über alle Seiten
Sortiment und Kategorieseiten zeigen den Filter als Leiste über den Kacheln, am Handy zugeklappt; Seitenzahlen und Trefferzahl beziehen sich auf das gefilterte Ergebnis.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | views/css/wpsg-theme.css | 13 | ||||
| -rw-r--r-- | views/mods/mod_productview/productview.js | 22 | ||||
| -rw-r--r-- | views/mods/mod_productview/productview_filter.phtml | 12 |
3 files changed, 41 insertions, 6 deletions
diff --git a/views/css/wpsg-theme.css b/views/css/wpsg-theme.css index e5d6727..4515211 100644 --- a/views/css/wpsg-theme.css +++ b/views/css/wpsg-theme.css @@ -649,6 +649,19 @@ html body .wpsg_product_garan_wrap a.wpsg_product_garan img { display:block; max /* Blöcke: Produktliste, Mini-Warenkorb, Kundenkonto */ .wpsg-block-product-list :where(.wpsg-product-list__count) { margin:0 0 var(--wpsg-gap); } .wpsg-block-product-list :where(.wpsg-product-list__count:empty) { display:none; } +/* Produktkacheln (Abfrage-Schleife, Kategorievorlage): Statuszeile des Filters und Filter als Leiste über den Kacheln */ +.wpsg-product-tiles :where(.wpsg-product-list__count) { margin:0 0 var(--wpsg-gap); } +.wpsg-product-tiles :where(.wpsg-product-list__count:empty) { display:none; } +.wpsg-product-tiles :where(.wpsg-block-product-filter) { margin:0 0 calc(var(--wpsg-gap) * 2) 0; } +.wpsg-product-tiles :where(.wpsg-pvf__fields) { display:flex; flex-wrap:wrap; align-items:flex-start; gap:var(--wpsg-gap) calc(var(--wpsg-gap) * 2); margin-top:var(--wpsg-gap); } +.wpsg-product-tiles :where(.wpsg-pvf__fields > .wpsg-pvf__item) { margin:0; } +.wpsg-product-tiles :where(.wpsg-pvf__fields > .wpsg-pvf__actions) { align-self:flex-end; } +.wpsg-pvf__summary { display:inline-flex; list-style:none; cursor:pointer; } +.wpsg-pvf__summary::-webkit-details-marker { display:none; } +@media (min-width:782px) { + .wpsg-pvf__toggle > .wpsg-pvf__summary { display:none; } + .wpsg-product-tiles :where(.wpsg-pvf__fields) { margin-top:0; } +} .wpsg-block-product-list :where(.wpsg-product-list__items) { display:grid; grid-template-columns:repeat(var(--wpsg-columns, 3), minmax(0, 1fr)); gap:calc(var(--wpsg-gap) * 2) var(--wpsg-gap); list-style:none; margin:0; padding:0; } .wpsg-block-product-list :where(.wpsg-product-list__item) { display:flex; flex-direction:column; gap:0.5em; min-width:0; margin:0; padding:0; } .wpsg-block-product-list :where(.wpsg-product-list__image img) { display:block; width:100%; height:auto; } diff --git a/views/mods/mod_productview/productview.js b/views/mods/mod_productview/productview.js index 34c0df9..fc58ec8 100644 --- a/views/mods/mod_productview/productview.js +++ b/views/mods/mod_productview/productview.js @@ -4,8 +4,9 @@ * Ohne JavaScript funktionieren Links und Formulare über die Adresse. Mit JavaScript holt das Skript die Ansicht per * Ajax (wpsg_mod=wpsg_mod_productview, wpsg_action=refresh) und schreibt den Zustand in die Adresse. Die Attribute des * Shortcodes kommen signiert aus dem Feld wpsg_atts; der Server übernimmt nur Seite, Sortierung, Ansicht und Filter. - * Produktlisten mit data-wpsg-filter (Block Produktliste) holt es mit der neuen Adresse als ganze Seite, wie ohne - * JavaScript, und tauscht ihren Inhalt; die Statuszeile bleibt stehen und sagt die neue Anzahl an. + * Produktlisten mit data-wpsg-filter (Block Produktliste, Produktkacheln) holt es mit der neuen Adresse als ganze Seite, + * wie ohne JavaScript, und tauscht ihren Inhalt; die Statuszeile und ein Filter darin bleiben stehen, damit Ansage und + * Fokus erhalten bleiben. */ ( function() { @@ -156,12 +157,13 @@ lists.forEach( function( list, i ) { - const status = list.querySelector( '.wpsg-product-list__count' ); + const status = list.querySelector( ':scope > .wpsg-product-list__count' ); + const keep = function( child ) { return child.classList.contains( 'wpsg-product-list__count' ) || child.classList.contains( 'wpsg-block-product-filter' ); }; - Array.prototype.slice.call( list.children ).forEach( function( child ) { if ( child !== status ) child.remove(); } ); - Array.prototype.slice.call( fresh[ i ].children ).forEach( function( child ) { if ( !child.classList.contains( 'wpsg-product-list__count' ) ) list.appendChild( document.importNode( child, true ) ); } ); + Array.prototype.slice.call( list.children ).forEach( function( child ) { if ( !keep( child ) ) child.remove(); } ); + Array.prototype.slice.call( fresh[ i ].children ).forEach( function( child ) { if ( !keep( child ) ) list.appendChild( document.importNode( child, true ) ); } ); - const freshStatus = fresh[ i ].querySelector( '.wpsg-product-list__count' ); + const freshStatus = fresh[ i ].querySelector( ':scope > .wpsg-product-list__count' ); if ( status && freshStatus ) status.textContent = freshStatus.textContent; list.removeAttribute( 'aria-busy' ); @@ -204,4 +206,12 @@ // Mit JavaScript sortiert die Auswahl sofort document.querySelectorAll( '.wpsg-pv__order-submit' ).forEach( function( b ) { b.hidden = true; } ); + // Filterleiste der Produktkacheln: am Handy zugeklappt, breit immer offen (Grenze wie WordPress, 782 px) + const narrow = window.matchMedia( '(max-width: 781px)' ); + + function toggleBar() { document.querySelectorAll( '.wpsg-pvf__toggle' ).forEach( function( d ) { d.open = !narrow.matches; } ); } + + toggleBar(); + narrow.addEventListener( 'change', toggleBar ); + } )(); diff --git a/views/mods/mod_productview/productview_filter.phtml b/views/mods/mod_productview/productview_filter.phtml index 121159a..1cf98da 100644 --- a/views/mods/mod_productview/productview_filter.phtml +++ b/views/mods/mod_productview/productview_filter.phtml @@ -25,6 +25,13 @@ <input type="hidden" name="<?php echo esc_attr($param); ?>" value="<?php echo esc_attr($value); ?>" /> <?php } ?> + <?php /* Leiste über den Produktkacheln: am Handy unter „Filter“ zugeklappt (productview.js), breit offen */ $bBar = (($this->view['wpsg_mod_productview_filter']['bar']??false) === true); ?> + <?php if ($bBar) { ?> + <details class="wpsg-pvf__toggle" open> + <summary class="wpsg-pvf__summary wpsg_button<?php echo wpsg_button_class(); ?>"><?php echo esc_html__('Filter', 'wpsg'); ?></summary> + <div class="wpsg-pvf__fields"> + <?php } ?> + <?php foreach ($this->view['showFilter'] as $filter) { ?> <?php if ($filter['type'] === 'catfilter') { ?> @@ -81,4 +88,9 @@ <?php } ?> </div> + <?php if ($bBar) { ?> + </div> + </details> + <?php } ?> + </form> |
