PVR
GitHub

JavaScript Helpers

What app.js does on every page and the shared helpers it provides.

2 min read
Updated June 20, 2026

assets/js/core/app.js is loaded on every page. It does two things:

  1. Auto-initializes the common UI on document.ready — you don't wire these up.
  2. Exposes a small API (app.*, API_CONFIG, window.i18n) your page scripts can call.

Page scripts live at assets/js/pages/<feature>/<page>.js and are included at the very end of the page's <body>.

Auto-initialized on load

When the page loads, app.js sets up:

  • Tooltips and popovers
  • The sidebar (accordion menus, slim-scroll, minify toggle, mobile drawer)
  • The header (search, fullscreen, notifications/chat offcanvas)
  • Date / datetime pickers, dropdowns
  • The theme toggle and the language switcher
  • The loading screen (hides it once ready)

So a typical page script only adds page-specific behavior (e.g. building a DataTable).

Toasts

app.toast.success('Saved successfully');
app.toast.error('Something went wrong');
app.toast.warning('Please confirm before continuing');
app.toast.info('Heads up — this is informational');
 
// optional custom heading / full options
app.toast.success('Saved', 'Done');
app.toast.show({ heading: 'Custom', text: 'Message', icon: 'success' });

Demo: toastNotifications.html.

Form validation helper

app.validation wraps jQuery Validate with the kit's defaults (Bootstrap is-invalid / is-valid styling, error placement inside .form-group):

app.validation.init('#myForm', {
    rules:    { email: { required: true, email: true } },
    messages: { email: { required: 'Email is required' } },
    submitHandler: function (form) { /* collect + submit */ }
});

You can also call jQuery Validate's $('#form').validate({...}) directly — that's what the formValidation.html demo does. See 04 — Forms › Validation.

DataTables helpers

Used by every list page (see 05 — Tables for the full recipe):

HelperDescription
app.datatables.getDom()Returns the standard dom layout string (length menu, filter, table, info, paging).
app.datatables.initDefaults()Applies global DataTables defaults.
app.datatables.initToolbar(api, table, opts)Builds the table toolbar. opts: addButton: {text, href}, expandButton: true, filterButton: true.
app.datatables.renderers.actionButtons([{className, icon, title}, …])Returns HTML for row action icon buttons.
app.datatables.renderSerialNumbers(api, colIndex)Fills a running serial-number column.
app.datatables.initProcessingState(selector)Shows the themed processing/loading state.
app.datatables.initExpandEvents(table, formatFn)Wires expandable child rows; formatFn(rowData) returns the child HTML.
$('#initDataTable').DataTable({
    dom: app.datatables.getDom(),
    columns: [ /* … */ ],
    columnDefs: [{
        targets: -1,
        render: () => app.datatables.renderers.actionButtons([
            { className: 'btn-edit', icon: 'edit',       title: 'Edit' },
            { className: 'btn-view', icon: 'visibility', title: 'View' }
        ])
    }],
    initComplete: function () {
        app.datatables.initToolbar(this.api(), table, {
            addButton: { text: 'Add', href: 'addMyPage.html' }, filterButton: true
        });
    },
    drawCallback: function () { app.datatables.renderSerialNumbers(this.api(), 0); }
});

Utilities

// Build DOM safely (returns a real element)
app.utils.createElement('div', {
    classes: ['btn', 'btn-primary'],
    attrs:   { id: 'saveBtn', type: 'button' },
    text:    'Save',
    children: [ /* more elements */ ]
});
 
// Safe nested lookup with optional fallback
app.utils.getValue(obj, 'a.b.c');        // undefined-safe
app.utils.getValue(value, '—');          // fallback when empty
 
// Short number formatting
app.formatNumberShort(1500000);          // → "1.5M"
app.formatNumberShort(2500);             // → "2.5K"

Inline editing

// Triggered by data-editable attributes in the markup (see 04 — Forms)
app.inlineEditable /* …popup / inline edit handlers… */

API_CONFIG — talking to your backend

The kit is a front end and ships with no server. If you wire it to your own API, use the API_CONFIG object in app.js to centralize the base URL, endpoint paths and headers:

fetch(API_CONFIG.getUrl(API_CONFIG.endpoints.RoleMaster.getRoleMaster), {
    headers: API_CONFIG.headers
})
.then(r => r.json())
.then(res => { /* res.data */ });
MemberWhat it is
API_CONFIG.baseUrlYour server's base URL. Set this to point the kit at your API.
API_CONFIG.endpointsA map of named endpoint paths grouped by feature (e.g. RoleMaster.getRoleMaster).
API_CONFIG.headersDefault request headers sent with each call.
API_CONFIG.getUrl(path)Joins baseUrl + an endpoint path into a full URL.

To add an endpoint, add it to the endpoints map in the API CONFIG section of app.js, then reference it via API_CONFIG.getUrl(API_CONFIG.endpoints.<Feature>.<name>). DataTables list pages pass that URL straight into the table's ajax option (see 05 — Tables).

i18n engine

app.js also boots the translation engine. The essentials:

window.i18n.setLocale('fr');     // switch language at runtime
window.i18n.getLocale();         // current language
window.i18n.t('roleMaster.mainPanelTitle');   // look up a key in code

Markup uses data-i18n attributes — full details in 09 — i18n.

Was this page helpful?