or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

behaviors.mdcollection-views.mdindex.mdobjects-and-application.mdregions.mdutilities.mdviews.md
tile.json

utilities.mddocs/

Utilities and Configuration

Utility functions for event binding, option merging, method normalization, and global configuration of DOM APIs and template renderers.

Capabilities

Event Binding Utilities

Functions for binding and unbinding events from entities (models, collections, other event emitters).

/**
 * Bind events from an entity to methods on the target object
 * @param entity - Object that triggers events (model, collection, etc.)
 * @param bindings - Hash of event names to method names or functions
 */
function bindEvents(entity: EventsEntity, bindings: EventsHash): void;

/**
 * Unbind events from an entity
 * @param entity - Object that triggers events
 * @param bindings - Hash of event names to method names or functions
 */
function unbindEvents(entity: EventsEntity, bindings: EventsHash): void;

Usage Examples:

import { bindEvents, unbindEvents, View } from "backbone.marionette";

class MyView extends View {
  initialize() {
    // Bind model events manually
    bindEvents(this.model, {
      'change': this.render,
      'change:name': 'onNameChange',
      'destroy': function() {
        console.log('Model destroyed');
      }
    });
  }
  
  onNameChange(model, name) {
    console.log('Name changed to:', name);
  }
  
  onDestroy() {
    // Unbind events on cleanup
    unbindEvents(this.model, {
      'change': this.render,
      'change:name': 'onNameChange'
    });
  }
}

// Can also be used with any event emitter
const eventEmitter = new Backbone.Events();
const handler = {
  onCustomEvent() {
    console.log('Custom event fired');
  }
};

bindEvents(eventEmitter, {
  'custom:event': handler.onCustomEvent
});

eventEmitter.trigger('custom:event'); // Handler called
unbindEvents(eventEmitter, { 'custom:event': handler.onCustomEvent });

Radio Request Utilities

Functions for binding and unbinding Backbone.Radio requests to methods.

/**
 * Bind Radio channel requests to methods on the target object
 * @param channel - Backbone.Radio channel
 * @param bindings - Hash of request names to method names or functions
 */
function bindRequests(channel: RadioChannel, bindings: RequestsHash): void;

/**
 * Unbind Radio channel requests
 * @param channel - Backbone.Radio channel
 * @param bindings - Hash of request names to method names or functions
 */
function unbindRequests(channel: RadioChannel, bindings: RequestsHash): void;

Usage Examples:

import { bindRequests, unbindRequests } from "backbone.marionette";
import Radio from "backbone.radio";

class UserService {
  constructor() {
    this.currentUser = null;
    this.channel = Radio.channel('users');
    
    // Bind requests to methods
    bindRequests(this.channel, {
      'current': 'getCurrentUser',
      'login': this.loginUser,
      'logout': () => {
        this.currentUser = null;
        return true;
      }
    });
  }
  
  getCurrentUser() {
    return this.currentUser;
  }
  
  loginUser(credentials) {
    // Login logic
    this.currentUser = { id: 1, name: credentials.username };
    return this.currentUser;
  }
  
  destroy() {
    // Cleanup requests
    unbindRequests(this.channel, {
      'current': 'getCurrentUser',
      'login': this.loginUser
    });
  }
}

// Usage
const userService = new UserService();
const channel = Radio.channel('users');

const user = channel.request('current'); // null
const loggedInUser = channel.request('login', { username: 'john' });
console.log(loggedInUser); // { id: 1, name: 'john' }

Option Management Utilities

Functions for managing options and configuration in Marionette objects.

/**
 * Merge specific keys from options onto the target object
 * @param options - Options object to merge from
 * @param keys - Array of key names to merge
 */
function mergeOptions(options: object, keys: string[]): void;

/**
 * Get an option value from the object's options or as a property
 * @param optionName - Name of the option to retrieve
 * @returns The option value or undefined
 */
function getOption(optionName: string): any;

Usage Examples:

import { mergeOptions, getOption, View } from "backbone.marionette";

class ConfigurableView extends View {
  constructor(options = {}) {
    super(options);
    
    // Merge specific options onto this object
    mergeOptions(options, ['apiUrl', 'timeout', 'debugMode']);
    
    // Now this.apiUrl, this.timeout, this.debugMode are set
    console.log('API URL:', this.apiUrl);
    console.log('Timeout:', this.timeout);
    console.log('Debug mode:', this.debugMode);
  }
  
  makeRequest() {
    // Use getOption to get values from options or properties
    const url = getOption.call(this, 'apiUrl') || '/api/default';
    const timeout = getOption.call(this, 'timeout') || 5000;
    
    // Make request with configured values
    console.log(`Making request to ${url} with timeout ${timeout}`);
  }
}

// Usage
const view = new ConfigurableView({
  apiUrl: 'https://api.example.com',
  timeout: 10000,
  debugMode: true
});

view.makeRequest(); // Uses merged options

Method Normalization Utilities

Functions for converting method name strings to actual function references.

/**
 * Convert method name strings to actual function references
 * @param hash - Hash object with method names as values
 * @returns Hash with method names converted to functions
 */
function normalizeMethods(hash: MethodsHash): NormalizedMethodsHash;

Usage Examples:

import { normalizeMethods, View } from "backbone.marionette";

class MyView extends View {
  initialize() {
    // Method names as strings
    const eventHandlers = {
      'click .button': 'onButtonClick',
      'submit form': 'onFormSubmit',
      'change input': this.onInputChange // Already a function
    };
    
    // Normalize to actual functions
    const normalizedHandlers = normalizeMethods.call(this, eventHandlers);
    
    console.log(typeof normalizedHandlers['click .button']); // 'function'
    console.log(typeof normalizedHandlers['submit form']); // 'function'
    console.log(typeof normalizedHandlers['change input']); // 'function'
  }
  
  onButtonClick() {
    console.log('Button clicked');
  }
  
  onFormSubmit() {
    console.log('Form submitted');
  }
  
  onInputChange() {
    console.log('Input changed');
  }
}

Trigger Method Utility

Function for triggering both events and corresponding onMethod handlers.

/**
 * Trigger both an event and its corresponding onMethod handler
 * @param event - Event name to trigger
 * @param args - Arguments to pass to handlers
 * @returns Result from onMethod if it exists
 */
function triggerMethod(event: string, ...args: any[]): any;

Usage Examples:

import { triggerMethod, View } from "backbone.marionette";

class MyView extends View {
  initialize() {
    // Listen to the event
    this.on('custom:event', (data) => {
      console.log('Event listener:', data);
    });
  }
  
  doSomething() {
    // Trigger both event and onMethod
    triggerMethod.call(this, 'custom:event', { message: 'Hello' });
    // This calls both the event listener above AND onCustomEvent method if it exists
  }
  
  onCustomEvent(data) {
    console.log('onMethod handler:', data);
    return 'handled';
  }
}

// Usage
const view = new MyView();
const result = view.doSomething();
// Logs:
// "Event listener: { message: 'Hello' }"
// "onMethod handler: { message: 'Hello' }"
console.log('Result:', result); // "handled"

Global Configuration Functions

Functions for configuring global behavior of Marionette components.

/**
 * Set custom DOM API for Views, CollectionViews, and Regions
 * @param mixin - DOM API mixin object with custom methods
 */
function setDomApi(mixin: DomApiMixin): void;

/**
 * Set custom template renderer for Views and CollectionViews
 * @param renderer - Template rendering function
 */
function setRenderer(renderer: RendererFunction): void;

Usage Examples:

import { setDomApi, setRenderer } from "backbone.marionette";

// Custom DOM API using native DOM methods
const customDomApi = {
  getEl(selector) {
    if (typeof selector === 'string') {
      return document.querySelectorAll(selector);
    }
    return [selector];
  },
  
  findEl(el, selector) {
    return el.querySelectorAll(selector);
  },
  
  setContents(el, html) {
    el.innerHTML = html;
  },
  
  appendContents(el, contents) {
    if (typeof contents === 'string') {
      el.insertAdjacentHTML('beforeend', contents);
    } else {
      el.appendChild(contents);
    }
  }
};

// Set custom DOM API globally
setDomApi(customDomApi);

// Custom template renderer using Handlebars
const handlebarsRenderer = (template, data) => {
  if (typeof template === 'string') {
    const compiled = Handlebars.compile(template);
    return compiled(data);
  } else if (typeof template === 'function') {
    return template(data);
  }
  return '';
};

// Set custom renderer globally
setRenderer(handlebarsRenderer);

// Now all views will use the custom DOM API and Handlebars renderer
class MyView extends View {
  template: '<h1>{{title}}</h1><p>{{content}}</p>' // Handlebars template
}

Feature Flag Utilities

Functions for managing feature flags in Marionette.

/**
 * Check if a feature flag is enabled
 * @param name - Feature flag name
 * @returns True if feature is enabled
 */
function isEnabled(name: string): boolean;

/**
 * Set a feature flag state
 * @param name - Feature flag name
 * @param state - Whether the feature should be enabled
 */
function setEnabled(name: string, state: boolean): void;

Usage Examples:

import { isEnabled, setEnabled } from "backbone.marionette";

// Enable a feature flag
setEnabled('newUI', true);
setEnabled('experimentalFeature', false);

// Check feature flags
if (isEnabled('newUI')) {
  console.log('Using new UI');
  // Load new UI components
} else {
  console.log('Using legacy UI');
  // Load legacy UI components
}

// In a view
class FeatureAwareView extends View {
  template() {
    if (isEnabled('experimentalFeature')) {
      return '<div class="experimental">Experimental content</div>';
    }
    return '<div class="standard">Standard content</div>';
  }
  
  behaviors() {
    const behaviors = {
      standard: StandardBehavior
    };
    
    if (isEnabled('experimentalFeature')) {
      behaviors.experimental = ExperimentalBehavior;
    }
    
    return behaviors;
  }
}

View Event Monitoring

Function for monitoring view state and propagating events to child views.

/**
 * Monitor view state and propagate attach/detach events to children
 * @param view - View to monitor
 */
function monitorViewEvents(view: View): void;

Usage Examples:

import { monitorViewEvents, View } from "backbone.marionette";

class ParentView extends View {
  initialize() {
    // Monitor this view for attach/detach events
    monitorViewEvents(this);
    
    // Listen for attach/detach events
    this.on('attach', this.onAttach);
    this.on('detach', this.onDetach);
  }
  
  onAttach() {
    console.log('Parent view attached to DOM');
    // Start animations, timers, etc.
  }
  
  onDetach() {
    console.log('Parent view detached from DOM');
    // Clean up animations, timers, etc.
  }
}

// Child views will automatically receive attach/detach events
class ChildView extends View {
  onAttach() {
    console.log('Child view attached to DOM');
  }
  
  onDetach() {
    console.log('Child view detached from DOM');
  }
}

Type Definitions

interface EventsEntity {
  on(event: string, callback: Function): void;
  off(event?: string, callback?: Function): void;
  trigger(event: string, ...args: any[]): void;
}

interface EventsHash {
  [eventName: string]: string | Function;
}

interface RequestsHash {
  [requestName: string]: string | Function;
}

interface MethodsHash {
  [key: string]: string | Function;
}

interface NormalizedMethodsHash {
  [key: string]: Function;
}

interface RadioChannel {
  request(requestName: string, ...args: any[]): any;
  trigger(eventName: string, ...args: any[]): void;
  reply(requestName: string, handler: Function): void;
  replyOnce(requestName: string, handler: Function): void;
  stopReplying(requestName?: string): void;
}

interface DomApiMixin {
  createBuffer?(): DocumentFragment;
  getDocumentEl?(el: Element): Document;
  getEl?(selector: string | Element): Element | Element[];
  findEl?(el: Element, selector: string): Element[];
  hasEl?(el: Element, childEl: Element): boolean;
  detachEl?(el: Element): void;
  replaceEl?(newEl: Element, oldEl: Element): void;
  swapEl?(el1: Element, el2: Element): void;
  setContents?(el: Element, html: string): void;
  appendContents?(el: Element, contents: Element | DocumentFragment | string, options?: object): void;
  hasContents?(el: Element): boolean;
  detachContents?(el: Element): DocumentFragment;
}

type RendererFunction = (template: string | Function, data: object) => string;

Advanced Usage Patterns

Custom Utility Mixins

// Create reusable utility mixins
const ApiMixin = {
  makeRequest(url, options = {}) {
    const apiUrl = getOption.call(this, 'apiUrl') || '';
    const timeout = getOption.call(this, 'timeout') || 5000;
    
    return fetch(apiUrl + url, {
      timeout,
      ...options
    });
  }
};

// Apply to views
class ApiEnabledView extends View {
  initialize(options) {
    mergeOptions(options, ['apiUrl', 'timeout']);
    _.extend(this, ApiMixin);
  }
  
  loadData() {
    return this.makeRequest('/data');
  }
}

Global Event System

// Set up global event system using utilities
const GlobalEvents = _.extend({}, Backbone.Events);

// Service that uses global events
class NotificationService {
  constructor() {
    bindEvents(GlobalEvents, {
      'user:login': 'onUserLogin',
      'user:logout': 'onUserLogout',
      'error': this.showError
    });
  }
  
  onUserLogin(user) {
    this.showNotification(`Welcome back, ${user.name}!`);
  }
  
  onUserLogout() {
    this.showNotification('You have been logged out.');
  }
  
  showError(error) {
    this.showNotification(`Error: ${error.message}`, 'error');
  }
  
  showNotification(message, type = 'info') {
    console.log(`[${type.toUpperCase()}] ${message}`);
  }
}

// Trigger global events from anywhere
GlobalEvents.trigger('user:login', { name: 'John Doe' });

Framework Utilities

Additional utilities provided by Marionette for framework extension and development.

/**
 * Backbone.extend utility for creating classes with inheritance
 * @param protoProps - Prototype properties to add to the class
 * @param staticProps - Static properties to add to the class constructor
 * @returns Extended class constructor
 */
function extend(protoProps: object, staticProps?: object): Function;

/**
 * Backbone.Events mixin for adding event capabilities to objects
 */
const Events: {
  on(eventName: string, callback: Function): this;
  off(eventName?: string, callback?: Function): this;
  trigger(eventName: string, ...args: any[]): this;
  once(eventName: string, callback: Function): this;
  listenTo(other: any, eventName: string, callback: Function): this;
  stopListening(other?: any, eventName?: string, callback?: Function): this;
};

Usage Examples:

import { extend, Events } from "backbone.marionette";

// Create a custom class using extend
const MyClass = extend({
  initialize() {
    console.log('MyClass initialized');
  },
  
  doSomething() {
    console.log('Doing something...');
  }
}, {
  // Static properties
  VERSION: '1.0.0'
});

// Add events to any object
const eventedObject = _.extend({}, Events);
eventedObject.on('custom:event', () => {
  console.log('Custom event triggered');
});
eventedObject.trigger('custom:event');