diff options
| author | Roger Rehnelt <noreply@maennchen1.de> | 2026-10-01 21:31:01 +0200 |
|---|---|---|
| committer | Roger Rehnelt <noreply@maennchen1.de> | 2026-10-01 21:31:01 +0200 |
| commit | 1615c1c0f81b056b5017d3d637f43b75ab8de4ca (patch) | |
| tree | ec30dd4f7d8f86ef09a5bf4aba85696e8e669b0d | |
| parent | f124d8990eb2042a9af25546738e4f5e64645aa8 (diff) | |
Produktfilter: nur die zuletzt gestellte Anfrage zählt
Zwei schnelle Änderungen am Filter konnten die Liste mit dem älteren Stand füllen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | views/mods/mod_productview/productview.js | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/views/mods/mod_productview/productview.js b/views/mods/mod_productview/productview.js index fc03a1f..34c0df9 100644 --- a/views/mods/mod_productview/productview.js +++ b/views/mods/mod_productview/productview.js @@ -53,11 +53,19 @@ } + // Laufende Anfragen je Ansicht (Position auf der Seite) und für die Produktlisten: Nur die zuletzt gestellte zählt + const pending = []; + let pendingLists = null; + function refresh( box, change, url, push ) { const field = box.querySelector( 'input[name="wpsg_atts"]' ); if ( !field ) return false; + const index = Array.prototype.indexOf.call( document.querySelectorAll( '.wpsg_productview' ), box ); + if ( pending[ index ] ) pending[ index ].abort(); + const ctl = pending[ index ] = new AbortController(); + const atts = JSON.parse( field.value ); Object.assign( atts, change ); @@ -66,10 +74,13 @@ box.classList.add( 'is-loading' ); box.setAttribute( 'aria-busy', 'true' ); - fetch( box.getAttribute( 'data-wpsg-pv-url' ) + ( box.getAttribute( 'data-wpsg-pv-url' ).indexOf( '?' ) === -1 ? '?' : '&' ) + params.toString(), { credentials: 'same-origin' } ) + fetch( box.getAttribute( 'data-wpsg-pv-url' ) + ( box.getAttribute( 'data-wpsg-pv-url' ).indexOf( '?' ) === -1 ? '?' : '&' ) + params.toString(), { credentials: 'same-origin', signal: ctl.signal } ) .then( function( r ) { if ( !r.ok ) throw new Error( r.status ); return r.text(); } ) .then( function( html ) { + if ( pending[ index ] !== ctl ) return; + pending[ index ] = null; + const tmp = document.createElement( 'div' ); tmp.innerHTML = html; @@ -77,11 +88,12 @@ if ( !fresh ) throw new Error( 'leer' ); fresh.querySelectorAll( '.wpsg-pv__order-submit' ).forEach( function( b ) { b.hidden = true; } ); - box.replaceWith( fresh ); + // Eine frühere Antwort kann die Ansicht schon ersetzt haben + document.querySelectorAll( '.wpsg_productview' )[ index ].replaceWith( fresh ); if ( url && push !== false ) history.pushState( { wpsgPv: true }, '', url ); } ) - .catch( function() { if ( url ) location.href = url; } ); + .catch( function() { if ( url && pending[ index ] === ctl ) location.href = url; } ); return true; @@ -129,10 +141,16 @@ lists.forEach( function( list ) { list.setAttribute( 'aria-busy', 'true' ); } ); - fetch( url, { credentials: 'same-origin' } ) + if ( pendingLists ) pendingLists.abort(); + const ctl = pendingLists = new AbortController(); + + fetch( url, { credentials: 'same-origin', signal: ctl.signal } ) .then( function( r ) { if ( !r.ok ) throw new Error( r.status ); return r.text(); } ) .then( function( html ) { + if ( pendingLists !== ctl ) return; + pendingLists = null; + const fresh = new DOMParser().parseFromString( html, 'text/html' ).querySelectorAll( '[data-wpsg-filter]' ); if ( fresh.length !== lists.length ) throw new Error( 'anders' ); @@ -151,7 +169,7 @@ } ); } ) - .catch( function() { location.href = url; } ); + .catch( function() { if ( pendingLists === ctl ) location.href = url; } ); } |
