JavaScript im Theme: pb:patch und Editor-Events

Widgets nach Section-Austausch neu initialisieren, Editor-Modus erkennen und auf Auswahl im PageBuilder reagieren.

Das Problem

Ändert ein Redakteur eine Einstellung, ersetzt der PageBuilder das DOM der Section vollständig. Slider, Akkordeons und andere Widgets verlieren dabei ihre Initialisierung – und DOMContentLoaded feuert nicht erneut.

Die Lösung: pb:patch

Nach jeder Änderung löst der Editor pb:patch am document aus. Initialisiere idempotent mit einem data-*-Flag:

function initSliders() {
  document.querySelectorAll('.js-slider').forEach((el) => {
    if (el.dataset.sliderInit) return
    el.dataset.sliderInit = '1'
    new Slider(el)
  })
}

document.addEventListener('DOMContentLoaded', initSliders)
document.addEventListener('pb:patch', initSliders)

Besser: Event-Delegation

Widgets, die nur auf Klicks reagieren, löst du mit einem delegierten Listener – er überlebt jeden Austausch. Klicks in bearbeitbare Felder ignorierst du:

document.addEventListener('click', (event) => {
  if (event.target.closest('[data-lf],[data-lf-block]')) return
  const head = event.target.closest('.accordion__head')
  if (!head) return
  head.parentElement.classList.toggle('is-open')
})

Editor-Modus erkennen

const isDesignMode = () => document.documentElement.hasAttribute('data-design-mode')

// Slider-Drag im Editor aus, damit Text markiert werden kann
new EmblaCarousel(root, { watchDrag: isDesignMode() ? false : undefined })

Auf Auswahl reagieren

EventWann
pb:section:loadSection wurde ausgetauscht (vor pb:patch)
pb:section:select / pb:section:deselectSection aus- bzw. abgewählt
pb:block:select / pb:block:deselectBlock aus- bzw. abgewählt
document.addEventListener('pb:block:select', (event) => {
  const item = event.target.closest('.accordion__item')
  if (item) item.classList.add('is-open')
})

Die Events bubbeln und tragen detail: { sectionId, blockId }.

Weitere Regeln

  • Kein document.write() – der statische Output verträgt keine synchronen DOM-Writes.

  • Section-Skripte über #element-{{ section.id }} scopen.

  • Bilder mit loading="lazy" und decoding="async" ausgeben.

Noch Fragen?

Unser Support antwortet in der Regel innerhalb eines Werktags.

Support kontaktieren