Javascript

Infinite Scrolling

Nach dieser äußerst repräsentativen Umfrage auf Mastodon, wie Infinite Scrolling bevorzugt genutzt wird, haben es drei von fünf Nutzern lieber interaktiv. Das heißt erst per Click wird neues Zeugs geladen.

Naja, dann kann ich ja meinen Infinite Scrolling Branch im Photoblog löschen…

Allerdings nicht ohne mal kurz aufzuschreiben wie ich das eigentlich umsetzen wollte.

Neue Fotos sollten immer eingeblendet werden, wenn die Unterkante der Seite erreicht ist, bzw. wenn der „Mehr Laden“-Button in den ViewPort scrollt.

Anstelle einer ulkigen scrollTopLengthHeightWasAuchImmer()-Konstruktion, habe ich es mit der Intersection Observer API versucht. Und das war ziemlich einfach:

// Das ist der Link mit dem Click Event zum Laden weiterer Fotos.
const loadMoreButton = document.querySelector('#load-more')

const loadMoreButtonObserver = new IntersectionObserver(
    (entries, options) => {
        for (let entry of entries) {
            if (entry.isIntersecting) {
                entry.target.click()
            }
        }
    }
)

if (loadMoreButton) {
    loadMoreButtonObserver.observe(loadMoreButton)
}

Ja, genau. Vieles geht mit plain Javascript sehr einfach. Ansonsten hat man ruckzuck wieder einen node_modules Ordner von etlichen Gigabytes, mit Packages zum Addieren zweier Integers oder so einen Krampf. Das muss nicht sein.

Überschreiben existierender Shopware Storefront Javascript Plugins

Trotz der Info Each JavaScript plugin can only be overridden once. If two Shopware plugins try to override the same plugin, only the last one of them will actually work. (Override Existing Javascript) hat mich irgendein Gedanke geritten, das könnte mehrfach gemacht werden.

Und so wollte ich einfach das OffCanvasCartPlugin aus der Storefront ein klein wenig erweitern und die Eingabe einer Postleitzahl im Offcanvas Cart ermöglichen - manchmal zur Lieferkostenberechnung unablässlich - und dabei die Infrastruktur zum Updaten von Feldern nutzen, die das Plugin schon mitbringt. Also einfach kurz das src/plugin/offcanvas-cart/offcanvas-cart.plugin extended, meine paar Methoden hinzugefügt und fertig. Dachte ich.

PluginManager.override('OffCanvasCart', 
    ZipExtensionOffcanvasCartPlugin, '[data-offcanvas-cart]'
);

Ich war wohl nicht der einzige, der das dachte. Beispielsweise im SwagAmazonPay Plugin wird das Offcanvas Dingelchen auch schon überschrieben. Und gemäß dem Motto "Die Letzten werden die Ersten sein" gewinnt natürlich das Plugins, das die letzte Überschreibung durchführt. Das war nicht meins.

Letztlich bleibt einem nichts anderes übrig die eigenen Erweiterung als neues Plugin zu registrieren. Allerdings muss man dann auch darauf achten, in dem selbst registrierten Plugin nicht nochmal alle Events erstellt werden, so dass der Offcanvas zwei Mal geöffnet wird etc. In diesem speziellen Fall mit dem Offcanvas Plugin war das einfach, indem ich die init() überschrieben habe ohne einen Aufruf von super.init()

export default class ZipExtensionOffcanvasCartPlugin
        extends OffCanvasCartPlugin {
    init() {
        this.client = new HttpClient()
        this._registerZipTriggerEvents()
    }

    _registerZipTriggerEvents() {
        this.$emitter.subscribe('offCanvasOpened', () => {
            const forms = DomAccess.querySelectorAll(
                document, '.js-offcanvas-cart-add-zip', false
            )
            if (forms) {
                Iterator.iterate(forms, 
                    form => form.addEventListener(
                        'submit', this._onAddZip.bind(this))
                    )
            }
        });
    }

    _onAddZip(event) {
        event.preventDefault()
        const form = event.target
        const selector = '.js-offcanvas-cart-zip'

        this.$emitter.publish('onAddZip')

        super._fireRequest(form, selector)
    }
}

Die Zip in die ShippingLocation über einen SalesChannelContextFactoryDecorator in den SalesChannelContexts zu bekommen und der vernünftige Umgang damit im Checkout war dann im Vergleich zu dem Javascript-Theater dann der wesentlich entspanntere Teil des Ganzen. Und ist vielleicht später mal einen Post wert.

Sharing Web Component

Nachdem ich Martin Schneiders Artikel Tinkering with Web Components gelesen habe, dachte ich, das wäre ein töfter Ersatz für die "Per E-Mail antworten" Funktion. Leicht abgewandelt wird auch der "Per E-Mail antworten"-Link über einen Share Button über eine Web Component angezeigt.

Und da ich gerade dabei war, gibt es noch drei weitere Web Components:

  • Der Now Playing Schnipsel rechts oben, der meinen gerade gecsrobbelten Titel anzeigt.
  • Die Vor-/Zurücknavigation unter den Posts
  • Die am häufigsten gespielten Alben auf der now-Seite