T3 JavaScript Framework
T3 is a client-side JavaScript framework for building large-scale web applications, developed and battle-hardened at Box. Its current stable version is 2.7.0. Unlike many modern frameworks, T3 is explicitly not an MVC framework and is designed to be unopinionated, providing a foundational structure for scalable client-side code rather than an all-encompassing solution. It promotes loose coupling, explicit dependencies, and progressive enhancement, allowing integration with other libraries like jQuery, Backbone, or React. T3 defines functionality through three core component types: Services (utility libraries), Modules (managing DOM element interactions), and Behaviors (mixins for shared event handling). Its release cadence has been irregular, with the last significant updates around 2017, focusing on stability rather than active feature development.
Common errors
-
ReferenceError: Box is not defined
cause The T3.js library script has not been loaded, or it was loaded after your application code attempted to access the global 'Box' object.fixEnsure that the `<script>` tag for `t3.js` is placed in your HTML *before* any custom JavaScript code that uses `Box.Application` or other T3 components. Verify the script path and network availability. -
TypeError: Box.Application.addModule is not a function
cause This error typically indicates that the `Box.Application` object is not available or fully initialized when `addModule` is called, usually because the `t3.js` script failed to load or loaded out of order.fixCheck the browser's developer console for errors during script loading. If you are using an async script load or defer, ensure your application code waits for the `DOMContentLoaded` event before interacting with T3. -
Error: Module 'my-module-name' not found on element
cause This error occurs when `Box.Application.start()` (or `init()`) attempts to find a module for a DOM element with a `data-module` attribute, but no corresponding module has been registered with `Box.Application.addModule()` for that specific name.fixVerify that the string value in your HTML's `data-module="my-module-name"` attribute exactly matches the module name provided in your JavaScript: `Box.Application.addModule('my-module-name', ...)`.
Warnings
- breaking Version 2.0.0 introduced significant breaking changes, including the removal of service exports from the T3 core and changes to internal APIs. Applications upgrading from 1.x to 2.x will require code modifications.
- gotcha The initial v2.0.0 release had issues with its release script, potentially leading to malformed builds or unexpected behavior. It is strongly advised to use version 2.0.1 or later.
- gotcha T3.js is primarily designed for use as a global library loaded via a <script> tag. It does not natively support modern module patterns like CommonJS `require()` or ES Module `import` syntax, which can lead to conflicts or difficulties in contemporary build environments.
- deprecated The project appears to be in maintenance mode, with the last significant release (v2.7.0) occurring in 2017. While the framework is stable, active feature development or prompt bug fixes for newly discovered issues are unlikely.
Install
-
npm install t3js -
yarn add t3js -
pnpm add t3js
Imports
- Box
import { Box } from 't3js'; // OR const Box = require('t3js');<!-- Load T3.js via script tag in HTML --> <script src="https://cdn.rawgit.com/box/t3js/v2.7.0/dist/t3.js"></script> // Then access globally in your JavaScript const app = Box.Application;
- Box.Application
import { Application } from 't3js'; // OR const app = require('t3js').Application;Box.Application.addModule('my-module', function(context) { /* ... */ }); - addModule
import { addModule } from 't3js.Application'; // OR Application.addModule('my-module', ...); // if 'Application' is not globally definedBox.Application.addModule('my-module', function(context) { var moduleEl; function init() { /* ... */ } function destroy() { /* ... */ } return { init: init, destroy: destroy }; });
Quickstart
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>T3 Quickstart</title>
<!-- Load T3.js - ensure this path is correct or use a CDN -->
<script src="https://cdn.rawgit.com/box/t3js/v2.7.0/dist/t3.js"></script>
</head>
<body>
<div data-module="my-greeter">
<h1 data-element="greeting-message">Loading...</h1>
<button data-behavior="greet-button">Say Hello</button>
</div>
<script>
// Define a T3 Module
Box.Application.addModule('my-greeter', function(context) {
var greetingMessageElement;
function init() {
greetingMessageElement = context.getElement('greeting-message');
// Attach a behavior for declarative event handling
context.attachBehavior('greet-button', greetBehavior);
updateGreeting('Initial message');
}
function destroy() {
greetingMessageElement = null;
}
function updateGreeting(message) {
if (greetingMessageElement) {
greetingMessageElement.textContent = message;
}
}
// Define a Behavior
var greetBehavior = {
onclick: function() {
const myService = context.getService('my-time-service');
const time = myService ? myService.getCurrentTime() : 'unknown time';
updateGreeting(`Hello from T3 at ${time}!`);
}
};
return {
init: init,
destroy: destroy,
// Expose a method if needed for other modules/services
updateMessage: updateGreeting
};
});
// Define a T3 Service
Box.Application.addService('my-time-service', function() {
function getCurrentTime() {
return new Date().toLocaleTimeString();
}
return { getCurrentTime: getCurrentTime };
});
// Initialize the T3 Application when the DOM is ready
document.addEventListener('DOMContentLoaded', function() {
Box.Application.init();
console.log('T3 Application Initialized.');
// You can also get a service directly after init
const timeService = Box.Application.getService('my-time-service');
if (timeService) {
console.log('Current time via service:', timeService.getCurrentTime());
}
});
</script>
</body>
</html>