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

# Tilpassede scripts

> Kør tilpasset JavaScript i Aftersell Cart med script-pladserne Initialization og On cart update.

Tilpassede scripts lader dig køre dit eget JavaScript mod carten ved brug af [Cart SDK](/da/aftersell/cart/sdk-overview). Tilføj dem i cart-editoren under **Cart settings → Custom script**, hvor en dropdown skifter mellem to pladser: **Initialization** og **On cart update**.

Skriv ren JavaScript i disse editorer, uden `<script>`-tags. **On cart update** har en **Reset to default**-handling, der gendanner dens startskabelon; **Initialization** har ikke, så gem din egen kopi, før du rydder den.

<Note>
  Meget af det, forhandlere tidligere scriptede, er nu en indbygget indstilling. Tjek først [Før du skriver et script](/da/aftersell/cart/sdk-use-cases#before-you-write-a-script): en indstilling bliver ved med at virke gennem cart-redesigns, og det gør dit script muligvis ikke.
</Note>

<div id="which-slot-to-use">
  ## Hvilken plads du skal bruge
</div>

|                  | Initialization                                                                                                                                                                    | On cart update                                              |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| **Kører**        | Én gang, når carten indlæses.                                                                                                                                                     | Ved hver cart-ændring efter den første indlæsning.          |
| **Du skriver**   | Hele scriptet.                                                                                                                                                                    | Kun handler-kroppen. `cart_updated`-wrapperen er låst.      |
| **Brug den til** | Registrering af adfærd én gang: [`configure`](/da/aftersell/cart/sdk-configure), [`events.on`](/da/aftersell/cart/sdk-events), [`hooks.register*`](/da/aftersell/cart/sdk-hooks). | Regler, der skal genevalueres mod cartens aktuelle indhold. |
| **Eksempel**     | Skjul gratis gave-linjer med en linjetransformation.                                                                                                                              | Hold en gratis gave synkroniseret med en forbrugstærskel.   |

<div id="initialization">
  ## Initialization
</div>

**Initialization**-scriptet kører **én gang, når carten indlæses**. Det er dit indgangspunkt til at sætte ting op: konfigurere cart-adfærd, abonnere på events og registrere hooks. [SDK'et](/da/aftersell/cart/sdk-overview) er tilgængeligt som `window.aftersell.cart`.

Opsætningskald, du foretager her ([`configure(...)`](/da/aftersell/cart/sdk-configure), [`events.on(...)`](/da/aftersell/cart/sdk-events), [`hooks.*`](/da/aftersell/cart/sdk-hooks)), er sikre at kalde øverst i scriptet, selv før carten er fuldt startet; de bufres og anvendes, når den er. Handlinger, der læser eller ændrer carten (som [`addItem`](/da/aftersell/cart/sdk-actions#additemvariantid-quantity) eller [`getCart`](/da/aftersell/cart/sdk-actions#getcart)), bør køre inde i [`ready()`](/da/aftersell/cart/sdk-overview#ready) eller en event-handler.

Pladsen starter med tre **udkommenterede** eksempler — åbning af skuffen ved hver tilføjelse, reaktion på `cart_loaded` og skjulning af gratis gave-linjer — så et urørt Initialization-script gør intet. Fjern kommentering fra ét for at prøve det, eller erstat dem.

Den naturlige form for denne plads er en **engangsregistrering uden events involveret**: registrér adfærden én gang, og lad carten anvende den fremover. At skjule gratis gave-linjer fra skuffen, uden at ændre totalen, er det medfølgende eksempel på det:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.hooks.registerLineTransform((line) => {
  if (line.finalLinePrice === 0) line.setHidden(true);
});
```

[`registerLineTransform`](/da/aftersell/cart/sdk-hooks#registerlinetransform) kører for hver linje, når den renderes, og `setHidden` er kun visning, så linjen bliver i carten og tæller stadig med i totalen, den vises bare ikke i skuffen. Se [Skjul og omdøb cart-linjer](/da/aftersell/cart/sdk-use-case-hide-lines) for mere om, hvad en transformation kan.

Handlinger, der læser carten, skal ind i `ready()`:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.ready().then(() => {
  const state = window.aftersell.cart.actions.getCart();
  console.log('Cart loaded with', state.itemCount, 'items');
});
```

At nå ind i cartens DOM kræver den samme ventetid, og det kræver [`shadowRoot`](/da/aftersell/cart/sdk-overview#shadowroot): carten renderes inde i en shadow root, så `document.querySelector` kan ikke se noget i skuffen.

<Tip>
  Forgrener du på marked, land eller valuta, **før** carten indlæses? Læs [`context`](/da/aftersell/cart/sdk-overview#context) i stedet. Den er tilgængelig synkront, uden behov for `ready()`, så du kan springe registrering af handlers helt over for kunder, en regel ikke gælder for.
</Tip>

<div id="on-cart-update">
  ## On cart update
</div>

**On cart update**-scriptet kører, hver gang carten ændres. Det er en låst wrapper omkring et `cart_updated`-abonnement, så du redigerer kun kroppen, og din kode modtager den opdaterede `cart`.

Denne plads er til regler, der skal **genevalueres ved hver cart-ændring**. En tærskel for en gratis gave er det klassiske tilfælde (brug \$75, få en gratis mulepose), fordi svaret afhænger af det aktuelle indhold, og intet andet kan fortælle dig, hvornår det ændres:

```js theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
window.aftersell.cart.events.on('cart_updated', (cart) => {
  const GIFT_VARIANT_ID = 1234567890;
  const THRESHOLD = 7500;   // $75.00, in cents

  let giftLine = null;
  let subtotal = 0;
  (cart.items ?? []).forEach((line) => {
    if (line.variantId === GIFT_VARIANT_ID) giftLine = line;
    else subtotal += line.finalLinePrice;   // the gift itself never counts toward the threshold
  });

  const shouldHaveGift = subtotal >= THRESHOLD;
  const hasGift = Boolean(giftLine);

  // Bail when the cart already matches. This is the part that matters: adding or
  // removing an item fires cart_updated again, so without this check the handler
  // re-enters itself forever.
  if (shouldHaveGift === hasGift) return;

  if (shouldHaveGift) window.aftersell.cart.actions.addItem(GIFT_VARIANT_ID, 1);
  else window.aftersell.cart.actions.removeItem(giftLine.key);
});
```

<div id="keeping-the-cart-in-a-desired-state">
  ### At holde carten i en ønsket tilstand
</div>

Linjen `if (shouldHaveGift === hasGift) return;` er det, der gør dette sikkert, og den generaliserer til alle scripts, der holder carten i en ønsket tilstand. Denne plads både reagerer på cart-ændringer og forårsager dem, så hvert `addItem` eller `removeItem` genindtræder i den. Beskriv den tilstand, du ønsker, sammenlign den med den tilstand, du har, og returnér tidligt, når de allerede stemmer overens, så handleren konvergerer efter én gennemgang i stedet for at loope. Se [de to regler](/da/aftersell/cart/sdk-events#the-two-rules) for den ubeskyttede version, du skal undgå, og hvorfor payloaden er skrivebeskyttet.

I en langsommere butik er det også værd at holde et in-flight-flag på modulniveau, så to hurtige ændringer ikke begge kan starte en tilføjelse, før den første lander.

<Note>
  `cart_updated` udløses kun ved ændringer **efter** den første indlæsning ([event-timing](/da/aftersell/cart/sdk-events#cart_updated)), så et script i denne plads afstemmer ikke en cart, der allerede kvalificerer sig, når siden indlæses. For en version, der håndterer begge, kan du abonnere på `cart_loaded` og `cart_updated` med den samme funktion fra **Initialization**-pladsen. Se [Tilføj automatisk en gratis gave ved en tærskel](/da/aftersell/cart/sdk-use-case-free-gift).
</Note>

<div id="when-a-script-breaks">
  ## Når et script fejler
</div>

Hver plads kører i sin egen sandbox, så et ødelagt **Initialization**-script kan ikke stoppe **On cart update** i at køre, og ingen af dem kan ødelægge selve carten.

Inden for en plads **stopper udførelsen dog ved den første fejl**. Alt under den linje springes over, hvilket betyder, at enhver `configure`, `events.on` eller `hooks.register*` længere nede aldrig registreres. Det er den sædvanlige forklaring på "min handler udløses aldrig", når koden ser rigtig ud.

Carten angiver den fejlende linje i browserkonsollen, og hver plads kører under sit eget filnavn (`aftersell-cart-init.js` og `aftersell-cart-cart-update.js`), så du kan åbne begge fra DevTools' Sources-panel og sætte breakpoints. Se [Fejlfinding](/da/aftersell/cart/sdk-overview#debugging) for de præcise beskeder og for debug-kanalen, der fanger hook-fejl, som holdes ude af konsollen.

Fordi `cart_loaded` [genafspilles for sene abonnenter](/da/aftersell/cart/sdk-events#cart_loaded), betyder registreringsrækkefølgen aldrig noget. Den sikreste struktur er at registrere alt først og udføre det risikable arbejde inde i handlers, hvor et throw er isoleret til den handler.

<div id="where-to-go-next">
  ## Hvor du kan gå hen herfra
</div>

* **[Cart SDK](/da/aftersell/cart/sdk-overview)**: tilpassede scripts er måden, du kører SDK-kode på. Se referencerne for [configure](/da/aftersell/cart/sdk-configure), [events](/da/aftersell/cart/sdk-events), [actions](/da/aftersell/cart/sdk-actions) og [hooks](/da/aftersell/cart/sdk-hooks) for hele overfladen, [cart-objektet](/da/aftersell/cart/sdk-cart-object) for formen på det, handlers modtager, og [use cases](/da/aftersell/cart/sdk-use-cases) for færdige snippets.
* **[Custom code-blokke](/da/aftersell/cart/custom-code-blocks)**: til at tilføje markup til carten. Bemærk, at Custom code-blokkens HTML-tilstand **ikke** kører JavaScript; brug tilpassede scripts (eller blokkens React-tilstand) til logik.
