> ## Documentation Index
> Fetch the complete documentation index at: https://dokumentation.websale.de/llms.txt
> Use this file to discover all available pages before exploring further.

# One-Page-Checkout

> Den dreiteiligen Bestellablauf als Akkordion auf einer Seite erscheinen lassen, ohne die drei Checkout-Seiten aufzugeben.

Der Bestellablauf in WEBSALE V8s besteht aus drei Seiten. Für den Käufer soll er aussehen wie eine einzige Seite mit drei aufklappbaren Abschnitten.

Die drei Seiten bleiben dabei erhalten. Nur das Umschalten zwischen ihnen sieht aus wie das Auf- und Zuklappen eines Abschnitts.

![Onepage](https://mintcdn.com/websaleag-44ee7ea6/HQq41690ljopUotf/images/onepage.jpg?fit=max\&auto=format\&n=HQq41690ljopUotf\&q=85\&s=34cc30b5199901f5cbab2468325760b3)

## Wie es funktioniert

Auf jeder der drei Seiten steht dasselbe Akkordion mit denselben drei Abschnitten. Gefüllt ist aber immer nur der Abschnitt, der zur aktuellen Seite gehört. In den beiden anderen steht lediglich eine Ladeanzeige.

| Seite | gefüllter Abschnitt |
| - | - |
| `ws_address_combined.htm` | 1. Rechnungs- und Lieferadresse |
| `ws_pay_deliv.htm` | 2. Zahlung und Versand |
| `ws_place_order.htm` | 3. Prüfen und Bestellen |

Klickt der Käufer auf einen der beiden anderen Abschnitte, passiert Folgendes:

1. Der offene Abschnitt klappt zu, der angeklickte klappt auf und zeigt die Ladeanzeige.
2. Nach einer halben Sekunde löst ein Skript die versteckte Schaltfläche aus, die zum gewünschten Schritt führt.
3. Die zugehörige Seite wird geladen, dort ist der passende Abschnitt bereits offen und gefüllt.

Der Seitenwechsel findet also statt, er fällt nur nicht auf, weil vorher schon das erscheint, was danach kommen soll.

> [!NOTE]
>
> Die Beispiele unten zeigen nur das Gerüst der Akkordions, ohne Shop-Tags und Includes. Was in den gefüllten Abschnitt gehört, ist der Inhalt, den Ihre Checkout-Seiten ohnehin haben.
>
> Gebaut ist das Gerüst mit den Akkordions von Bootstrap 5. Mit einem anderen Framework ändern sich die Klassen- und Attributnamen.

## Schritt 1: Das Gerüst auf allen drei Seiten

Alle drei Seiten tragen dasselbe Grundgerüst. Unterschiedlich sind nur drei Dinge: welcher Abschnitt offen ist, welcher Abschnitt Inhalt hat und welche versteckten Schaltflächen darin stehen.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<div id="wsCheckoutCollapse" class="accordion">

   <div class="accordion-item">
      <h2 class="accordion-header">
         <button class="accordion-button collapsed" type="button"
                 data-bs-toggle="collapse" data-bs-target="#wsCheckoutCollapseChild01"
                 aria-expanded="false"
                 onclick="wsOnePageCheckoutLoad('<ID der Schaltfläche>');">
            1. Rechnungs- und Lieferadresse
         </button>
      </h2>
      <div id="wsCheckoutCollapseChild01" class="accordion-collapse collapse"
           data-bs-parent="#wsCheckoutCollapse">
         <div class="accordion-body">
            <span class="spinner-border" role="status" aria-label="wird geladen"></span>
         </div>
      </div>
   </div>

   <!-- Abschnitt 2 und 3 nach demselben Muster -->

</div>
```

Das gemeinsame `data-bs-parent` sorgt dafür, dass immer nur ein Abschnitt offen ist. Ohne diese Angabe ließen sich mehrere gleichzeitig aufklappen, und der Käufer sähe zwei Ladeanzeigen nebeneinander.

Die Kopfzeile gehört in ein Überschriftenelement. Bootstrap sieht dafür `h2` vor. Mit einem `div` fehlt der Seite ihre Gliederung, und wer per Überschriftenliste navigiert, findet die Schritte nicht.

> [!WARNING]
>
> Die Ladeanzeige braucht einen Namen. Ein `span` ohne Textinhalt ist für Hilfsmittel nichts. `role="status"` und ein `aria-label` machen daraus eine wahrnehmbare Meldung.

## Schritt 2: Der offene Abschnitt je Seite

Der Abschnitt, der zur aktuellen Seite gehört, ist offen, enthält den eigentlichen Inhalt und bekommt **kein** `onclick`:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<div class="accordion-item">
   <h2 class="accordion-header">
      <button class="accordion-button" type="button"
              data-bs-toggle="collapse" data-bs-target="#wsCheckoutCollapseChild02"
              aria-expanded="true">
         2. Zahlung und Versand
      </button>
   </h2>
   <div id="wsCheckoutCollapseChild02" class="accordion-collapse collapse show"
        data-bs-parent="#wsCheckoutCollapse">
      <div class="accordion-body">
         <!-- der eigentliche Inhalt der Seite -->

         <button id="wsPayDelivNextBtn" name="~BT-PayDeliv_Next~" type="submit" hidden>Weiter</button>
         <button id="wsPayDelivBackBtn" name="~BT-PayDeliv_Back~" type="submit" hidden>Zurück</button>
      </div>
   </div>
</div>
```

> [!WARNING]
>
> **Der offene Abschnitt darf kein `onclick` tragen.**
>
> In der bisherigen Beschreibung hat der offene Abschnitt auf der Bestellübersichtsseite eines, und zwar auf `wsPayDelivNextBtn`. Diese Schaltfläche gibt es auf dieser Seite nicht, sie gehört zur Zahlungs- und Versandartenseite. Klickt der Käufer auf den ohnehin offenen Abschnitt, um ihn zuzuklappen, bricht das Skript mit einem Fehler ab.
>
> Auf den beiden anderen Seiten ist es richtig gelöst, dort trägt der offene Abschnitt kein `onclick`.

## Schritt 3: Welche Schaltfläche zu welchem Ziel führt

| Von Seite | Ziel | Schaltfläche | Tag |
| - | - | - | - |
| Bestellübersicht | Adresse | `wsPlaceOrderChangeAddrBtn` | `BT-Change_Addr` |
| Bestellübersicht | Zahlung und Versand | `wsPlaceOrderChangePayDelivBtn` | `BT-Change_PayDeliv` |
| Zahlung und Versand | Adresse | `wsPayDelivBackBtn` | `BT-PayDeliv_Back` |
| Zahlung und Versand | Bestellübersicht | `wsPayDelivNextBtn` | `BT-PayDeliv_Next` |
| Adresse | Zahlung und Versand | `wsAddressNextBtn` | `BT-Addr_Next` |
| Adresse | Bestellübersicht | `wsAddressChangeBtn` | `BT-Addr_Change` |

Die versteckten Schaltflächen stehen jeweils im **gefüllten** Abschnitt, weil sie innerhalb des Formulars dieser Seite liegen müssen. Sind entsprechende Schaltflächen bereits sichtbar vorhanden, können Sie deren Kennungen verwenden und auf die versteckten verzichten.

Statt `style="display: none;"` genügt das Attribut `hidden`. Es wirkt genauso, lässt sich im Stylesheet überschreiben und hält die Gestaltung aus dem Template heraus.

Referenz: [BT-Change\_Addr](https://dokumentation.websale.de/v8s/referenz/tags/bt/bestellprozess.md#die-tags-im-uberblick) · [BT-Change\_PayDeliv](https://dokumentation.websale.de/v8s/referenz/tags/bt/bestellprozess.md#die-tags-im-uberblick) · [BT-PayDeliv\_Next](https://dokumentation.websale.de/v8s/referenz/tags/bt/bestellprozess.md#die-tags-im-uberblick) · [BT-PayDeliv\_Back](https://dokumentation.websale.de/v8s/referenz/tags/bt/bestellprozess.md#die-tags-im-uberblick) · [BT-Addr\_Next](https://dokumentation.websale.de/v8s/referenz/tags/bt/adressen.md#die-tags-im-uberblick) · [BT-Addr\_Change](https://dokumentation.websale.de/v8s/referenz/tags/bt/adressen.md#die-tags-im-uberblick)

## Schritt 4: Das Skript

Auf allen drei Seiten:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<script>
function wsOnePageCheckoutLoad(buttonID) {
   var button = document.querySelector("#" + buttonID);
   if (button === null) {
      return;
   }

   if (window.innerWidth < 768) {
      window.scrollTo({ top: 0, behavior: "smooth" });
   }

   window.setTimeout(function () {
      button.click();
   }, 500);
}
</script>
```

Die Prüfung auf `null` fängt den Fall ab, dass eine Schaltfläche auf der aktuellen Seite nicht vorhanden ist. Ohne sie bricht das Skript ab und der Käufer sitzt vor einer Ladeanzeige, die nie verschwindet.

> [!NOTE]
>
> Die halbe Sekunde Verzögerung gibt dem Akkordion Zeit, seine Bewegung zu Ende zu führen, bevor die Seite wechselt. Ohne sie springt die Darstellung.
>
> Sie ist damit eine reine Darstellungspause. Jeder Schritt im Checkout dauert dadurch eine halbe Sekunde länger, als er müsste.

Das Hochscrollen auf schmalen Bildschirmen verhindert, dass der Käufer nach dem Seitenwechsel irgendwo in der Mitte der neuen Seite landet.

## Was Sie beachten sollten

> [!WARNING]
>
> Ohne JavaScript klappt das Akkordion auf und zeigt dauerhaft die Ladeanzeige. Der Käufer kommt dann nicht weiter.
>
> Halten Sie deshalb die regulären Schaltflächen für den nächsten und vorigen Schritt erreichbar, statt sie durch das Akkordion zu ersetzen. Sie sind der Weg, der in jedem Fall funktioniert.
>
> Ein Klick auf einen anderen Abschnitt sendet das Formular der aktuellen Seite ab. Auf der Adressseite bedeutet das, dass die Eingaben geprüft werden. Enthalten sie Fehler, bleibt der Käufer auf der Adressseite, und zwar mit den Fehlermeldungen, aber ohne den Abschnitt, den er anklicken wollte.
>
> Das ist richtig so. Weisen Sie den Käufer in diesem Fall deutlich darauf hin, warum der Schritt nicht ausgeführt wurde, sonst wirkt die Oberfläche defekt.

Der Käufer sieht drei Abschnitte, von denen zwei leer sind. Beschriften Sie die beiden geschlossenen Abschnitte deshalb mit dem, was dort bereits erfasst wurde, beispielsweise der gewählten Zahlungsart. Dann ist das Akkordion zugleich eine Übersicht über den Stand der Bestellung.

## Verwandte Themen

* Wegweiser: [Bestellprozess](https://dokumentation.websale.de/v8s/referenz/tags/bt/bestellprozess.md)
* Wegweiser: Ausgabe im Bestellprozess
* Wegweiser: [Zahlungsarten anlegen](https://dokumentation.websale.de/v8s/zahlungsarten-anlegen/zahlungsarten-anlegen.md)
* Referenz: [BT- (Schaltflächen)](https://dokumentation.websale.de/v8s/referenz/tags/bt/adressen.md)


## Related topics

- [Checkout](https://dokumentation.websale.de/frontend/referenz/aktionen/checkout.md)
- [Bestellablauf](https://dokumentation.websale.de/frontend/funktionsubersicht/bestellablauf.md)
- [Anwendungsbeispiele](https://dokumentation.websale.de/v8s/anwendungsbeispiele/anwendungsbeispiele.md)
- [checkout - Bestellablauf](https://dokumentation.websale.de/konfiguration/checkout-bestellablauf.md)
- [Materialien Parameterentfernung](https://dokumentation.websale.de/v8s/materialien/materialien-parameterentfernung.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.