🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
123 lines
6.1 KiB
JavaScript
Executable File
123 lines
6.1 KiB
JavaScript
Executable File
/**
|
|
* JQHTML Integration - Component Registration and Hydration Bootstrap
|
|
*
|
|
* This module bridges RSpade's manifest system with jqhtml's component runtime.
|
|
*
|
|
* == TWO-PHASE INITIALIZATION ==
|
|
*
|
|
* Phase 1: _on_framework_modules_define() - Component Registration
|
|
* - Runs early in framework boot, before DOM is processed
|
|
* - Registers all ES6 classes extending Component with jqhtml runtime
|
|
* - Tags static methods with cache IDs for jqhtml's caching system
|
|
* - After this phase, jqhtml knows: "User_Card" → UserCardClass
|
|
*
|
|
* Phase 2: _on_framework_modules_init() - DOM Hydration
|
|
* - Calls jqhtml.boot() to hydrate all ._Component_Init placeholders
|
|
* - Triggers 'jqhtml_ready' when all components are initialized
|
|
*
|
|
* == KEY PARTICIPANTS ==
|
|
*
|
|
* JqhtmlBladeCompiler.php - Transforms <Component /> tags into ._Component_Init divs
|
|
* jqhtml runtime - Maintains registry of component names → classes
|
|
* jqhtml.boot() - Finds and hydrates all ._Component_Init placeholders
|
|
* This module - Orchestrates registration and triggers hydration
|
|
*/
|
|
class Jqhtml_Integration {
|
|
/**
|
|
* Phase 1: Register Component Classes
|
|
*
|
|
* Compiled .jqhtml templates self-register their render methods with jqhtml.
|
|
* But the framework must separately register ES6 component classes (the ones
|
|
* extending Component with lifecycle methods like on_create, on_load, etc).
|
|
*
|
|
* This runs during framework_modules_define, before any DOM processing.
|
|
*/
|
|
static _on_framework_modules_define() {
|
|
// ─────────────────────────────────────────────────────────────────────
|
|
// Register Component Classes with jqhtml Runtime
|
|
//
|
|
// The Manifest knows all classes extending Component. We register each
|
|
// with jqhtml so it can instantiate them by name during hydration.
|
|
// ─────────────────────────────────────────────────────────────────────
|
|
let jqhtml_components = Manifest.get_extending('Component');
|
|
console_debug('JQHTML_INIT', 'Registering ' + jqhtml_components.length + ' Components');
|
|
|
|
for (let component of jqhtml_components) {
|
|
jqhtml.register_component(component.class_name, component.class_object);
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────
|
|
// Tag Static Methods with Cache IDs
|
|
//
|
|
// jqhtml caches component renders based on a hash of their args.
|
|
// Problem: Functions can't be serialized, so passing one (e.g., a
|
|
// DataGrid's data_source callback) would defeat caching entirely.
|
|
//
|
|
// Solution: Tag every static method with a stable string identifier.
|
|
// When jqhtml hashes component args, it uses _jqhtml_cache_id instead
|
|
// of the function reference, making the cache key deterministic.
|
|
//
|
|
// Example:
|
|
// <My_DataGrid $data_source=Controller.fetch />
|
|
//
|
|
// Without tagging: args hash includes [Function] → uncacheable
|
|
// With tagging: args hash includes "Controller.fetch" → cacheable
|
|
//
|
|
// This enables Ajax endpoints and other callbacks to be passed to
|
|
// components without breaking the automatic caching system.
|
|
// ─────────────────────────────────────────────────────────────────────
|
|
const all_classes = Manifest.get_all_classes();
|
|
let methods_tagged = 0;
|
|
|
|
for (const class_info of all_classes) {
|
|
const class_object = class_info.class_object;
|
|
const class_name = class_info.class_name;
|
|
const property_names = Object.getOwnPropertyNames(class_object);
|
|
|
|
for (const property_name of property_names) {
|
|
if (property_name === 'length' || property_name === 'name' || property_name === 'prototype') {
|
|
continue;
|
|
}
|
|
|
|
const property_value = class_object[property_name];
|
|
if (typeof property_value === 'function') {
|
|
property_value._jqhtml_cache_id = `${class_name}.${property_name}`;
|
|
methods_tagged++;
|
|
}
|
|
}
|
|
}
|
|
|
|
console_debug('JQHTML_INIT', `Tagged ${methods_tagged} static methods with _jqhtml_cache_id`);
|
|
|
|
// ─────────────────────────────────────────────────────────────────────
|
|
// Configure jqhtml Caching
|
|
//
|
|
// scope_key() changes when: app code changes, user logs out, site changes.
|
|
// This automatically invalidates cached component renders.
|
|
// ─────────────────────────────────────────────────────────────────────
|
|
jqhtml.set_cache_key(Rsx.scope_key());
|
|
window.jqhtml.debug.verbose = false;
|
|
}
|
|
|
|
/**
|
|
* Phase 2: DOM Hydration
|
|
*
|
|
* Delegates to jqhtml.boot() which finds all ._Component_Init placeholders
|
|
* and converts them into live components.
|
|
*
|
|
* jqhtml.boot() handles:
|
|
* - Finding ._Component_Init elements
|
|
* - Parsing data-component-init-name / data-component-args
|
|
* - Calling $element.component(name, args)
|
|
* - Recursive nested component handling
|
|
* - Promise tracking for async components
|
|
*/
|
|
static _on_framework_modules_init() {
|
|
jqhtml.boot().then(() => {
|
|
Rsx.trigger('jqhtml_ready');
|
|
});
|
|
}
|
|
}
|
|
|
|
// Class is automatically made global by RSX manifest - no window assignment needed
|