Extending the frontend UI 

For UI that needs to run in the browser - status badges, comment indicators, custom toolbar buttons - the extension exposes a small, stable facade on window.XimaFrontendEdit and dispatches DOM CustomEvents at defined lifecycle points. Internal refactors of the underlying JavaScript do not change these method signatures or event detail shapes - this is the one part of the frontend JavaScript covered by a semver guarantee.

Facade methods 

getElementInfo(uid) 

Returns the resolved target element and payload for a content element uid, so consumers never have to re-do DOM resolution (anchor pattern, translation mapping). Returns null if the uid was not rendered.

const info = window.XimaFrontendEdit.getElementInfo(42);
// { uid: 42, element: HTMLElement, payload: { element: {...}, menu: {...} } }
Copied!

notify({ title, message, severity }) 

Shows a toast notification using the extension's own notification manager. severity is one of ok, info, warning, error.

window.XimaFrontendEdit.notify({
    title: 'Comment added',
    message: 'A new comment was posted on this element.',
    severity: 'info',
});
Copied!

registerToolbarItem(uid, buttonSpec) 

Adds a button to a content element's hover toolbar, next to the built-in Edit/More actions buttons. buttonSpec:

  • html - inner HTML of the button (e.g. an inline SVG icon)
  • label - accessible label, also used as the tooltip
  • href - renders an <a> instead of a <button>
  • onClick - click handler
window.XimaFrontendEdit.registerToolbarItem(42, {
    html: '<svg>...</svg>',
    label: 'Show comments',
    onClick: () => openCommentsPanel(42),
});
Copied!

registerBadge(uid, spec) 

Renders a persistent, hover-independent indicator on a content element's overlay - useful for "live annotating" a page, where a marker must be visible at a glance rather than only on hover. spec:

  • html or element - the badge content (HTML string or a DOM element)
  • position - one of top-left, top-right (default), bottom-left, bottom-right
  • id - when given, a later call with the same uid + id replaces this badge in place instead of adding a duplicate (useful since xfe:element-rendered can fire more than once for the same element)
  • onClick - click handler; the badge only receives pointer events when this is set

Multiple badges registered for the same corner lay out in a row, in registration order, instead of overlapping - each corner is its own slot, created on first use.

window.XimaFrontendEdit.registerBadge(42, {
    html: '<span class="my-badge" title="3 comments">3</span>',
    position: 'top-left',
    id: 'comment-count',
    onClick: () => openCommentsPanel(42),
});
Copied!

setBadgeMode(mode) 

Sets a display-mode hook for badges: 'subtle' (default) or 'prominent', exposed as document.documentElement's data-xfe-badge-mode attribute. The extension ships no badge content itself (see registerBadge above), so it has no opinion on what "subtle" vs "prominent" should actually look like - write your own CSS against the attribute:

window.XimaFrontendEdit.setBadgeMode('prominent');
Copied!
A consumer's own stylesheet
/* Small dot only, by default */
.my-badge-label { display: none; }
/* Full label once prominent mode is active */
[data-xfe-badge-mode="prominent"] .my-badge-label { display: inline; }
Copied!

openBackendView(url, options) 

Opens a backend URL in the version-appropriate container: the contextual sidebar (v14.2+, when enabled and available), the v13 iframe modal, or a new tab as a fallback - no version checks needed in consumer code. The returnUrl flash-message deferral mechanism used by edit forms is applied automatically. options:

  • target - 'tab' forces a new tab regardless of version
  • title - shown in the container's header
  • width - a CSS length (e.g. '600px', '50%'); invalid values are ignored
  • onClose - called with { reason } when the container closes (reason is 'close', or 'saved' for the sidebar's own save flow)
  • reloadOnClose - reload the parent page on close (default true)
  • linkPolicy - a rule or array of rules { match: string | RegExp, action }, evaluated against link clicks inside the embedded document. action is one of:

    • stay (default when nothing matches) - keep navigation inside the container, same as today's built-in behavior
    • close - close the container
    • ignore - swallow the click, do nothing
    • external - open the link in a new tab

    The policy only ever governs plain link clicks - the built-in save/close buttons of an actual edit form keep working exactly as before.

window.XimaFrontendEdit.openBackendView(commentsBackendUrl, {
    title: 'Comments',
    width: '480px',
    linkPolicy: { match: '/typo3/module/web/layout', action: 'close' },
    onClose: ({ reason }) => console.log('comments panel closed:', reason),
});
Copied!

Lifecycle events 

All events are dispatched on document.

xfe:ready 

Fired once, after the initial AJAX render (or immediately, with an empty map, when frontend editing is disabled).

  • detail.elements - plain object keyed by content element uid, each value shaped like the getElementInfo() return value

xfe:element-rendered 

Fired once per content element, right after its overlay/toolbar is built.

  • detail.uid, detail.element, detail.payload - same as getElementInfo()
  • detail.overlay, detail.toolbar, detail.dropdown - the underlying DOM nodes (dropdown is null when the element has no context menu)

xfe:dropdown-open / xfe:dropdown-close 

Fired when a content element's "More actions" dropdown opens or closes. detail.uid identifies the element. Only fires for an actual open/close interaction - hovering between elements does not trigger a spurious xfe:dropdown-close for a dropdown that was never open.

document.addEventListener('xfe:element-rendered', (event) => {
    const { uid, payload } = event.detail;
    if (payload.element.CType === 'list' && payload.element.list_type === 'news_pi1') {
        window.XimaFrontendEdit.registerBadge(uid, { html: '<span>News</span>' });
    }
});
Copied!

Minimal integration example 

A third-party extension listening for rendered elements
document.addEventListener('xfe:ready', (event) => {
    console.log('Frontend Edit ready with', Object.keys(event.detail.elements).length, 'element(s)');
});

document.addEventListener('xfe:element-rendered', (event) => {
    const { uid } = event.detail;
    window.XimaFrontendEdit.registerToolbarItem(uid, {
        label: 'Open comments',
        onClick: () => window.XimaFrontendEdit.openBackendView('/comments/' + uid),
    });
});
Copied!