Builder JavaScript

JS Production Builder

Select the components your project needs and compile them into a single minified production bundle. Core modules are always included. The output overwrites view/front/themes/master/js/wf-production.min.js .

Build Configuration

0 components selected
Build Output
Ready. Select components and click Build Bundle.

Core Files

Always included in every bundle — these provide the base runtime, DOM utilities, and internationalization support. They cannot be deselected.

File Description Included
wf-base.js All WF JS components extend WojoBase. Responsibilities: always
wf-utils.js Helpers used by multiple components — import only what you need. always
wf-i18n.js Simple, zero-dependency translation registry used by all WF components for any UI strings they generate (aria labels, button text, etc.). always

Components

Select the components to include. Only checked components are bundled — unused code is excluded to keep the output lean.

Editor Build

Compile all editor modules into a single minified file. The output overwrites view/front/themes/master/js/wf-editor.min.js. The bundle exposes window.WojoEditor with init() and WojoI18n. Set data-wf-editor-mode on the container element to control the editor mode declaratively — simple, hybrid, or advanced.

Build Output
Ready. Click Build Editor Bundle to compile.

Usage

Always load the framework bundle before the editor bundle — both use defer, so they execute in declaration order after parsing completes. Wrap the footer script in DOMContentLoaded so it runs after both deferred bundles have executed. The framework auto-inits components from data-wf-* attributes; component defaults and i18n are the only things that need an explicit call. Each bundle has its own isolated WojoI18n instance — init both with the same URL; English is built-in and skipped automatically, non-English locales fetch the JSON once and the browser cache serves the second call at no extra cost.

Editor content is kept in sync with a hidden <textarea> inside your CMS form. Add data-wf-editor-for="editor" to the textarea — the editor reads the initial value from it on load and writes JSON back automatically when the form submits. No save handler or per-page JS required; the field name, form action, and method all live in HTML.

HTML
<!-- 1. Bundles — framework first, editor second (both deferred, run in declaration order) -->
<script defer src="/assets/wf-production.min.js"></script>
<script defer src="/assets/wf-editor.min.js"></script>

<!-- 2. CMS form — all fields including editor content submit together via standard POST.
     Each CMS section (blog post, page, product…) sets its own action URL and fields;
     the footer JS never changes. -->
<form method="post" action="/cms/api/save-post">

    <input  name="title" value="<?= htmlspecialchars($row['title']) ?>">
    <input  name="slug"  value="<?= htmlspecialchars($row['slug'])  ?>">

    <!-- Hidden textarea linked to the editor by matching data-wf-editor-for to the editor id.
         • Initial value: PHP renders DB content here (plain HTML or editor JSON).
         • On submit:     editor writes its current JSON into this field automatically.
         • On server:     read $_POST['content'] like any other form field. -->
    <textarea name="content" data-wf-editor-for="editor" hidden><?= $row['content'] ?></textarea>

    <!-- Editor container — mode and toolbar position come from data attributes -->
    <div id="editor" data-wf-editor-mode="hybrid" data-wf-toolbar-position="attached"></div>

    <!-- Toolbar is optional — remove the element entirely if not needed -->
    <div id="editor-toolbar" class="be-editor-toolbar" role="banner">
        <div class="be-editor-toolbar-slot" data-be-toolbar-slot="history"></div>
        <div class="be-toolbar-spacer"></div>
        <div class="be-editor-toolbar-slot" data-be-toolbar-slot="responsive"></div>
        <div class="be-editor-toolbar-slot" data-be-toolbar-slot="renders"></div>
        <div class="be-editor-toolbar-slot" data-be-toolbar-slot="actions"></div>
    </div>
    <div id="be-preview-pane" class="be-preview-pane" hidden></div>

    <button type="submit">Save</button>

</form>

<!-- 3. Footer JS — identical on every CMS page; nothing here changes per section -->
<script>
document.addEventListener('DOMContentLoaded', function () {

    // ── Framework ─────────────────────────────────────────────────────────────
    // Components auto-init from data-wf-* attributes — no extra JS needed.
    // Set global defaults for components that require project-specific config.
    const { WojoDatePicker } = WojoFramework.components['wf-date-picker'];
    WojoDatePicker.setDefaults({
        weekStart: 1,            // 0 = Sunday · 1 = Monday
        format:    'dd/mm/yyyy', // 'mm/dd/yyyy' · 'yyyy-mm-dd'
    });

    // ── i18n ─────────────────────────────────────────────────────────────────
    // Each bundle has its own WojoI18n instance — init both with the same URL.
    // English (<html lang="en">) is built-in; init() is a no-op for English.
    // Non-English: JSON fetched once by the first bundle, served from browser
    // cache for the second — no extra network request.
    const i18nUrl = '/assets/i18n/{locale}.json';
    WojoFramework.core['wf-i18n'].WojoI18n.init(i18nUrl);
    if (window.WojoEditor) WojoEditor.WojoI18n.init(i18nUrl);

    // ── Editor ────────────────────────────────────────────────────────────────
    // The editor auto-discovers the linked textarea via data-wf-editor-for="editor"
    // and reads initial content from its value. On form submit the editor writes
    // its current JSON back into the textarea — no save handler required.
    const editorEl = document.getElementById('editor');
    if (!editorEl) return;

    const editor = WojoEditor.init(editorEl, {
        urls: {
            imageList:         '/api/api-list-images.php',
            imageUpload:       '/api/api-upload-image.php',
            videoUpload:       '/api/api-upload-video.php',
            linkList:          '/api/api-list-links.php',
            blockTemplateList: '/api/api-block-templates.php',
            colorsUrl:         '/themes/master/css/wf-colors.css',
            iconList:          '/themes/master/css/wf-icons.css',
            previewCss:        '/themes/master/css/main.css',
            previewJs:         '/assets/wf-production.min.js',
        },
    });

    // ── Toolbar (optional) ────────────────────────────────────────────────────
    const toolbarEl = document.getElementById('editor-toolbar');
    if (toolbarEl) {
        editor.mountToolbar({
            toolbar:           toolbarEl,
            previewPane:       document.getElementById('be-preview-pane'),
            editorRoot:        editorEl,
            defaultOutputView: 'none',
        });
    }
});
</script>