Document .once() method and 'loaded' event, update npm packages

Update npm packages including @jqhtml/core

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2026-03-06 23:50:01 +00:00
parent 198cd42ce1
commit 3294fc7337
22 changed files with 292 additions and 82 deletions

View File

@@ -974,22 +974,36 @@ CREATING COMPONENTS
LIFECYCLE EVENT CALLBACKS
External code can register callbacks for lifecycle events using
the .on() method. Useful when you need to know when a component
reaches a certain state.
the .on() and .once() methods. Useful when you need to know when
a component reaches a certain state.
Supported Events:
'render' - Fires after render phase completes
'create' - Fires after create phase completes
'load' - Fires after load phase completes (data available)
'loaded' - Fires after on_loaded() completes (this.data set and frozen)
'ready' - Fires after ready phase completes (fully initialized)
Methods:
.on(event, callback) - Register callback, fires on every occurrence
.once(event, callback) - Register callback, fires only once
Both methods share the same behavior:
- If the event already fired, callback executes immediately
- Returns this for chaining
- Custom events also supported (see CUSTOM COMPONENT EVENTS)
The difference: .on() fires on every future occurrence (useful for
re-renders), while .once() fires at most once and then removes itself.
Awaiting Data in Async Methods:
When a method needs data that may not be loaded yet, await the 'load'
event. If the event already fired, the callback executes immediately:
When a method needs data that may not be loaded yet, await the
'loaded' event. If the event already fired, the callback executes
immediately. Use .once() since you only need notification once:
async get_display_name() {
// Wait for on_load() to complete if not already
await new Promise(resolve => this.on('load', resolve));
await new Promise(resolve => this.once('loaded', resolve));
return `${this.data.first_name} ${this.data.last_name}`;
}
@@ -1004,6 +1018,11 @@ LIFECYCLE EVENT CALLBACKS
// Access component data, DOM, etc.
});
// Fire only once (even across re-renders)
component.once('ready', (comp) => {
console.log('First ready!', comp);
});
// Chain directly
$('#my-component').component().on('ready', (component) => {
console.log('User data:', component.data.user);
@@ -1013,17 +1032,16 @@ LIFECYCLE EVENT CALLBACKS
component
.on('render', () => console.log('Dashboard rendered'))
.on('create', () => console.log('Dashboard created'))
.on('load', () => console.log('Dashboard data loaded'))
.on('loaded', () => console.log('Dashboard data loaded'))
.on('ready', () => console.log('Dashboard ready'));
Key behaviors:
- Immediate execution: If lifecycle event already occurred,
callback fires immediately
- Future events: Callback also registers for future occurrences
(useful for re-renders)
callback fires immediately (both .on() and .once())
- .on(): Callback persists for future occurrences (re-renders)
- .once(): Callback fires once then auto-removes
- Multiple callbacks: Can register multiple for same event
- Chaining: Returns this so you can chain .on() calls
- Custom events also supported (see CUSTOM COMPONENT EVENTS)
- Chaining: Both return this so you can chain calls
Example - Wait for component initialization:
// React when dashboard component is ready
@@ -1031,14 +1049,12 @@ LIFECYCLE EVENT CALLBACKS
console.log('Dashboard loaded:', this.data);
});
// Process component data after load
$('#data-grid').component().on('load', (comp) => {
// One-time notification when data loads
$('#data-grid').component().once('loaded', (comp) => {
const total = comp.data.items.reduce((sum, i) => sum + i.value, 0);
$('#total').text(total);
});
Available in JQHTML v2.2.81+
CUSTOM COMPONENT EVENTS
Components can fire and listen to custom events using the jqhtml event
bus. Unlike jQuery's .trigger()/.on(), the jqhtml event bus guarantees
@@ -1059,6 +1075,11 @@ CUSTOM COMPONENT EVENTS
console.log('Event data:', data);
});
// Listen only once
this.sid('child_component').once('my_event', (component, data) => {
console.log('First occurrence only');
});
From external code:
$('#element').component().on('my_event', (component, data) => {
// Handle event
@@ -1066,6 +1087,7 @@ CUSTOM COMPONENT EVENTS
Callback Signature:
.on('event_name', (component, data) => { ... })
.once('event_name', (component, data) => { ... })
- component: The component instance that fired the event
- data: Optional data passed as second argument to trigger()
@@ -1109,14 +1131,14 @@ EVENT HANDLER PLACEMENT
Where to register event handlers depends on what you're attaching to:
Component Events (this.on()) - Register in on_create():
Component Events (this.on()/this.once()) - Register in on_create():
Component events attach to this.$ which persists across re-renders.
Register once in on_create() to avoid infinite loops.
on_create() {
// Component event - register once
this.on('file-drop', (_, data) => this._handle(data));
this.on('custom-event', (_, data) => this._process(data));
this.once('initialized', () => this._setup());
}
DANGER: If registered in on_ready() and the handler triggers
@@ -1146,9 +1168,9 @@ EVENT HANDLER PLACEMENT
}
Summary:
this.on('event', ...) → on_create() (component events)
this.sid('child').on('event') → on_ready() (child component events)
this.$sid('elem').on('click') → on_render() (child DOM events)
this.on/once('event', ...) → on_create() (component events)
this.sid('child').on/once('event') → on_ready() (child component events)
this.$sid('elem').on('click') → on_render() (child DOM events)
$REDRAWABLE ATTRIBUTE - LIGHTWEIGHT COMPONENTS
Convert any HTML element into a re-renderable component using the

View File

@@ -222,7 +222,7 @@ BREADCRUMB SYSTEM
// Helper to await loaded data
async _await_loaded() {
if (this.data.contact && this.data.contact.id) return;
await new Promise(resolve => this.on('load', resolve));
await new Promise(resolve => this.once('loaded', resolve));
}
async page_title() {
@@ -248,17 +248,17 @@ BREADCRUMB SYSTEM
Awaiting Loaded Data:
Breadcrumb methods are called BEFORE on_load() completes. If a method
needs loaded data (e.g., contact name), it must await the 'load' event:
needs loaded data (e.g., contact name), it must await the 'loaded' event:
async _await_loaded() {
// Check if data is already loaded
if (this.data.contact && this.data.contact.id) return;
// Otherwise wait for 'load' event
await new Promise(resolve => this.on('load', resolve));
// Otherwise wait for 'loaded' event
await new Promise(resolve => this.once('loaded', resolve));
}
The 'load' event fires immediately if already past that lifecycle
phase, so this pattern is safe to call multiple times.
The 'loaded' event fires after on_load() completes and this.data is
set. Using once() is appropriate since it only needs to fire once.
RSX_BREADCRUMB_RESOLVER
Framework class that handles breadcrumb resolution with caching.

View File

@@ -641,8 +641,8 @@ async add_item() {
| What | Where | Why |
|------|-------|-----|
| `this.on('event', ...)` | `on_create()` | Persists across renders; on_ready() risks infinite loops from event replay |
| `this.sid('child').on('event')` | `on_ready()` | Child component events |
| `this.on/once('event', ...)` | `on_create()` | Persists across renders; on_ready() risks infinite loops from event replay |
| `this.sid('child').on/once('event')` | `on_ready()` | Child component events |
| `this.$sid('elem').on('click')` | `on_render()` or `on_ready()` | Child DOM recreated on render, must re-attach |
### Loading Pattern
@@ -692,6 +692,8 @@ From within component methods:
Fire: `this.trigger('event_name', data)` | Listen: `this.sid('child').on('event_name', (component, data) => {})`
**Methods**: `.on(event, cb)` fires on every occurrence. `.once(event, cb)` fires once then auto-removes. Both fire immediately if event already happened and return `this` for chaining.
**Key difference from jQuery**: Events fired BEFORE handler registration still trigger the callback when registered. This solves component lifecycle timing issues where child events fire before parent registers handlers. Never use `this.$.trigger()` for custom events (enforced by JQHTML-EVENT-01).
### Dynamic Component Creation

24
node_modules/.package-lock.json generated vendored
View File

@@ -2224,9 +2224,9 @@
}
},
"node_modules/@jqhtml/core": {
"version": "2.3.39",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/core/-/core-2.3.39.tgz",
"integrity": "sha512-qyxOBcoFCaf35etqvNOSJppqT4WQLfD9O2b8bAv5la4oSpRUmXSjVJFdv3cSMIK8qClXbupN8bm4FLbAalJqog==",
"version": "2.3.41",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/core/-/core-2.3.41.tgz",
"integrity": "sha512-Owf8Rf7yjG+WSRCPTXtTg+pFpWbTB+MnB/g2Clo6rVWZ5JxEqFZfmKIDx6lSX30pz16ph3RShe9Ijjc8V89S3w==",
"license": "MIT",
"dependencies": {
"@rollup/plugin-node-resolve": "^16.0.1",
@@ -2250,9 +2250,9 @@
}
},
"node_modules/@jqhtml/parser": {
"version": "2.3.39",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/parser/-/parser-2.3.39.tgz",
"integrity": "sha512-DLPwZf1X7enf2lVOaFaIWlu8vQYMgk/+Lioup2w4F07oXFx2+MnFgcJ/Ie9Pf6VUnMT1IOIZQxOd/5QugwFFDA==",
"version": "2.3.41",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/parser/-/parser-2.3.41.tgz",
"integrity": "sha512-q6pT+eqWQf0qEgxzb61nERro5NkIeBnu/DQPUqRNZdywAqam8AHYlwzA5n54BlghJ6m/61DVeRMSHoVu1UV6lA==",
"license": "MIT",
"dependencies": {
"@types/jest": "^29.5.11",
@@ -2290,9 +2290,9 @@
}
},
"node_modules/@jqhtml/ssr": {
"version": "2.3.39",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/ssr/-/ssr-2.3.39.tgz",
"integrity": "sha512-//MaIub8tel8w6l3AiqvoW021Aj9JR8BlVrZsezAO7svAIgsMFTeFdLKUud1+rg8I5Nxe4DE8CiGHz+f3Ts0kA==",
"version": "2.3.41",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/ssr/-/ssr-2.3.41.tgz",
"integrity": "sha512-9uNQ7QaaBBU49ncEKxv9uoajfxe3/vt1wLOMrex81oqKB1PHFIkfQbQ1QcNakYgDTXMFkXKinH0O3qEROH9Lxw==",
"license": "MIT",
"dependencies": {
"jquery": "^3.7.1",
@@ -2386,9 +2386,9 @@
}
},
"node_modules/@jqhtml/vscode-extension": {
"version": "2.3.39",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/vscode-extension/-/vscode-extension-2.3.39.tgz",
"integrity": "sha512-Zi0iS5/t+5IhQoZP54J1/OOFB2OdoM6TM3g37SMJmPKjIDBUt883M3POszKFJwfj8+lrBV5OeJPOmPu3m9RYOQ==",
"version": "2.3.41",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/vscode-extension/-/vscode-extension-2.3.41.tgz",
"integrity": "sha512-CB3tIppMT3cVLiOIAAxymMtLAae2FJfkf6aFSkQOiONK47h10k2/QkkXFJwXyRRnzbw+ijuhBCDodiLlJtt8aw==",
"license": "MIT",
"engines": {
"vscode": "^1.74.0"

View File

@@ -21,6 +21,17 @@
* @param callback - Callback: (component, data?) => void
*/
export declare function event_on(component: any, event_name: string, callback: (comp: any, data?: any) => void): any;
/**
* Register a callback that fires exactly once.
*
* - If the event already occurred (sticky), fires immediately and does NOT register.
* - If the event has not occurred, registers and auto-deregisters after first fire.
*
* @param component - The component instance
* @param event_name - Name of the event
* @param callback - Callback: (component, data?) => void
*/
export declare function event_once(component: any, event_name: string, callback: (comp: any, data?: any) => void): any;
/**
* Trigger an event - fires all registered callbacks.
* Marks event as occurred so future .on() calls fire immediately.

View File

@@ -1 +1 @@
{"version":3,"file":"component-events.d.ts","sourceRoot":"","sources":["../src/component-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,GAAG,CAqB3G;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,CAelF;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAG/E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAEzE"}
{"version":3,"file":"component-events.d.ts","sourceRoot":"","sources":["../src/component-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,GAAG,CAqB3G;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,GAAG,CA+B7G;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,CAelF;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAG/E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAEzE"}

View File

@@ -53,6 +53,7 @@ export declare class Jqhtml_Component {
private _load_only;
private _load_render_only;
_is_detached: boolean;
private _force_initial_render;
private _has_rendered;
private _load_queue;
private __has_custom_on_load;
@@ -344,6 +345,12 @@ export declare class Jqhtml_Component {
* @see component-events.ts for full documentation
*/
on(event_name: string, callback: (component: Jqhtml_Component, data?: any) => void): this;
/**
* Register a callback that fires exactly once - delegates to component-events.ts
* If the event already occurred, fires immediately and does not register.
* @see component-events.ts for full documentation
*/
once(event_name: string, callback: (component: Jqhtml_Component, data?: any) => void): this;
/**
* Trigger a lifecycle event - delegates to component-events.ts
* @see component-events.ts for full documentation

View File

@@ -1 +1 @@
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"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"}

View File

@@ -2199,6 +2199,46 @@ function event_on(component, event_name, callback) {
}
return component;
}
/**
* Register a callback that fires exactly once.
*
* - If the event already occurred (sticky), fires immediately and does NOT register.
* - If the event has not occurred, registers and auto-deregisters after first fire.
*
* @param component - The component instance
* @param event_name - Name of the event
* @param callback - Callback: (component, data?) => void
*/
function event_once(component, event_name, callback) {
// If event already occurred, fire immediately and we're done
if (component._lifecycle_states.has(event_name)) {
try {
const stored_data = component._lifecycle_states.get(event_name);
callback(component, stored_data);
}
catch (error) {
console.error(`[JQHTML] Error in ${event_name} once callback:`, error);
}
return component;
}
// Wrap callback to auto-deregister after first fire
const wrapper = (comp, data) => {
// Remove ourselves from the callback list
const callbacks = component._lifecycle_callbacks.get(event_name);
if (callbacks) {
const idx = callbacks.indexOf(wrapper);
if (idx !== -1)
callbacks.splice(idx, 1);
}
callback(comp, data);
};
// Initialize callback array for this event if needed
if (!component._lifecycle_callbacks.has(event_name)) {
component._lifecycle_callbacks.set(event_name, []);
}
component._lifecycle_callbacks.get(event_name).push(wrapper);
return component;
}
/**
* Trigger an event - fires all registered callbacks.
* Marks event as occurred so future .on() calls fire immediately.
@@ -2847,7 +2887,11 @@ class Jqhtml_Component {
this._load_render_only = false;
// Detached optimization: true when element is not in the DOM at boot time.
// Skips initial render and cache read — just on_load then render.
// Override with _force_initial_render to keep normal double-render behavior.
this._is_detached = false;
// _force_initial_render: override detached optimization — render even when not in DOM.
// Use when you need the loading spinner visible immediately after appending.
this._force_initial_render = false;
// rendered event - fires once after the synchronous render chain completes
// (after on_load's re-render if applicable, or after first render if no on_load)
this._has_rendered = false;
@@ -2906,6 +2950,9 @@ class Jqhtml_Component {
if (this.args._load_render_only === true) {
this._load_render_only = true;
}
if (this.args._force_initial_render === true) {
this._force_initial_render = true;
}
// Attach component to element
this.$.data('_component', this);
// Apply CSS classes and attributes
@@ -3396,7 +3443,7 @@ class Jqhtml_Component {
// Suppressed by _load_only and _load_render_only flags (preloading mode)
if (!this._load_only && !this._load_render_only) {
await this._call_lifecycle('on_loaded');
this.trigger('on_loaded');
this.trigger('loaded');
}
});
return data_changed;
@@ -3417,7 +3464,8 @@ class Jqhtml_Component {
// Don't await - on_create MUST be sync. The warning is enough.
}
// Detect detached elements — skip cache and initial render for elements not in DOM
this._is_detached = !this.$[0].isConnected;
// _force_initial_render overrides this optimization
this._is_detached = !this.$[0].isConnected && !this._force_initial_render;
// OPTIMIZATION: Skip cache operations and snapshot if no custom on_load()
// Components without on_load() don't fetch data, so nothing to cache or restore
if (this.__has_custom_on_load) {
@@ -3463,7 +3511,7 @@ class Jqhtml_Component {
this.trigger('load');
if (!this._load_only && !this._load_render_only) {
await this._call_lifecycle('on_loaded');
this.trigger('on_loaded');
this.trigger('loaded');
}
return;
}
@@ -3543,7 +3591,7 @@ class Jqhtml_Component {
this.trigger('load');
if (!this._load_only && !this._load_render_only) {
await this._call_lifecycle('on_loaded');
this.trigger('on_loaded');
this.trigger('loaded');
}
return;
}
@@ -3623,7 +3671,7 @@ class Jqhtml_Component {
// Suppressed by _load_only and _load_render_only flags (preloading mode)
if (!this._load_only && !this._load_render_only) {
await this._call_lifecycle('on_loaded');
this.trigger('on_loaded');
this.trigger('loaded');
}
}
finally {
@@ -4080,6 +4128,14 @@ class Jqhtml_Component {
on(event_name, callback) {
return event_on(this, event_name, callback);
}
/**
* Register a callback that fires exactly once - delegates to component-events.ts
* If the event already occurred, fires immediately and does not register.
* @see component-events.ts for full documentation
*/
once(event_name, callback) {
return event_once(this, event_name, callback);
}
/**
* Trigger a lifecycle event - delegates to component-events.ts
* @see component-events.ts for full documentation
@@ -5280,7 +5336,7 @@ function init(jQuery) {
}
}
// Version - will be replaced during build with actual version from package.json
const version = '2.3.39';
const version = '2.3.41';
// Default export with all functionality
const jqhtml = {
// Core

File diff suppressed because one or more lines are too long

View File

@@ -2195,6 +2195,46 @@ function event_on(component, event_name, callback) {
}
return component;
}
/**
* Register a callback that fires exactly once.
*
* - If the event already occurred (sticky), fires immediately and does NOT register.
* - If the event has not occurred, registers and auto-deregisters after first fire.
*
* @param component - The component instance
* @param event_name - Name of the event
* @param callback - Callback: (component, data?) => void
*/
function event_once(component, event_name, callback) {
// If event already occurred, fire immediately and we're done
if (component._lifecycle_states.has(event_name)) {
try {
const stored_data = component._lifecycle_states.get(event_name);
callback(component, stored_data);
}
catch (error) {
console.error(`[JQHTML] Error in ${event_name} once callback:`, error);
}
return component;
}
// Wrap callback to auto-deregister after first fire
const wrapper = (comp, data) => {
// Remove ourselves from the callback list
const callbacks = component._lifecycle_callbacks.get(event_name);
if (callbacks) {
const idx = callbacks.indexOf(wrapper);
if (idx !== -1)
callbacks.splice(idx, 1);
}
callback(comp, data);
};
// Initialize callback array for this event if needed
if (!component._lifecycle_callbacks.has(event_name)) {
component._lifecycle_callbacks.set(event_name, []);
}
component._lifecycle_callbacks.get(event_name).push(wrapper);
return component;
}
/**
* Trigger an event - fires all registered callbacks.
* Marks event as occurred so future .on() calls fire immediately.
@@ -2843,7 +2883,11 @@ class Jqhtml_Component {
this._load_render_only = false;
// Detached optimization: true when element is not in the DOM at boot time.
// Skips initial render and cache read — just on_load then render.
// Override with _force_initial_render to keep normal double-render behavior.
this._is_detached = false;
// _force_initial_render: override detached optimization — render even when not in DOM.
// Use when you need the loading spinner visible immediately after appending.
this._force_initial_render = false;
// rendered event - fires once after the synchronous render chain completes
// (after on_load's re-render if applicable, or after first render if no on_load)
this._has_rendered = false;
@@ -2902,6 +2946,9 @@ class Jqhtml_Component {
if (this.args._load_render_only === true) {
this._load_render_only = true;
}
if (this.args._force_initial_render === true) {
this._force_initial_render = true;
}
// Attach component to element
this.$.data('_component', this);
// Apply CSS classes and attributes
@@ -3392,7 +3439,7 @@ class Jqhtml_Component {
// Suppressed by _load_only and _load_render_only flags (preloading mode)
if (!this._load_only && !this._load_render_only) {
await this._call_lifecycle('on_loaded');
this.trigger('on_loaded');
this.trigger('loaded');
}
});
return data_changed;
@@ -3413,7 +3460,8 @@ class Jqhtml_Component {
// Don't await - on_create MUST be sync. The warning is enough.
}
// Detect detached elements — skip cache and initial render for elements not in DOM
this._is_detached = !this.$[0].isConnected;
// _force_initial_render overrides this optimization
this._is_detached = !this.$[0].isConnected && !this._force_initial_render;
// OPTIMIZATION: Skip cache operations and snapshot if no custom on_load()
// Components without on_load() don't fetch data, so nothing to cache or restore
if (this.__has_custom_on_load) {
@@ -3459,7 +3507,7 @@ class Jqhtml_Component {
this.trigger('load');
if (!this._load_only && !this._load_render_only) {
await this._call_lifecycle('on_loaded');
this.trigger('on_loaded');
this.trigger('loaded');
}
return;
}
@@ -3539,7 +3587,7 @@ class Jqhtml_Component {
this.trigger('load');
if (!this._load_only && !this._load_render_only) {
await this._call_lifecycle('on_loaded');
this.trigger('on_loaded');
this.trigger('loaded');
}
return;
}
@@ -3619,7 +3667,7 @@ class Jqhtml_Component {
// Suppressed by _load_only and _load_render_only flags (preloading mode)
if (!this._load_only && !this._load_render_only) {
await this._call_lifecycle('on_loaded');
this.trigger('on_loaded');
this.trigger('loaded');
}
}
finally {
@@ -4076,6 +4124,14 @@ class Jqhtml_Component {
on(event_name, callback) {
return event_on(this, event_name, callback);
}
/**
* Register a callback that fires exactly once - delegates to component-events.ts
* If the event already occurred, fires immediately and does not register.
* @see component-events.ts for full documentation
*/
once(event_name, callback) {
return event_once(this, event_name, callback);
}
/**
* Trigger a lifecycle event - delegates to component-events.ts
* @see component-events.ts for full documentation
@@ -5276,7 +5332,7 @@ function init(jQuery) {
}
}
// Version - will be replaced during build with actual version from package.json
const version = '2.3.39';
const version = '2.3.41';
// Default export with all functionality
const jqhtml = {
// Core

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
/**
* JQHTML Core v2.3.39
* JQHTML Core v2.3.41
* (c) 2025 JQHTML Team
* Released under the MIT License
*/
@@ -2200,6 +2200,46 @@ function event_on(component, event_name, callback) {
}
return component;
}
/**
* Register a callback that fires exactly once.
*
* - If the event already occurred (sticky), fires immediately and does NOT register.
* - If the event has not occurred, registers and auto-deregisters after first fire.
*
* @param component - The component instance
* @param event_name - Name of the event
* @param callback - Callback: (component, data?) => void
*/
function event_once(component, event_name, callback) {
// If event already occurred, fire immediately and we're done
if (component._lifecycle_states.has(event_name)) {
try {
const stored_data = component._lifecycle_states.get(event_name);
callback(component, stored_data);
}
catch (error) {
console.error(`[JQHTML] Error in ${event_name} once callback:`, error);
}
return component;
}
// Wrap callback to auto-deregister after first fire
const wrapper = (comp, data) => {
// Remove ourselves from the callback list
const callbacks = component._lifecycle_callbacks.get(event_name);
if (callbacks) {
const idx = callbacks.indexOf(wrapper);
if (idx !== -1)
callbacks.splice(idx, 1);
}
callback(comp, data);
};
// Initialize callback array for this event if needed
if (!component._lifecycle_callbacks.has(event_name)) {
component._lifecycle_callbacks.set(event_name, []);
}
component._lifecycle_callbacks.get(event_name).push(wrapper);
return component;
}
/**
* Trigger an event - fires all registered callbacks.
* Marks event as occurred so future .on() calls fire immediately.
@@ -2848,7 +2888,11 @@ class Jqhtml_Component {
this._load_render_only = false;
// Detached optimization: true when element is not in the DOM at boot time.
// Skips initial render and cache read — just on_load then render.
// Override with _force_initial_render to keep normal double-render behavior.
this._is_detached = false;
// _force_initial_render: override detached optimization — render even when not in DOM.
// Use when you need the loading spinner visible immediately after appending.
this._force_initial_render = false;
// rendered event - fires once after the synchronous render chain completes
// (after on_load's re-render if applicable, or after first render if no on_load)
this._has_rendered = false;
@@ -2907,6 +2951,9 @@ class Jqhtml_Component {
if (this.args._load_render_only === true) {
this._load_render_only = true;
}
if (this.args._force_initial_render === true) {
this._force_initial_render = true;
}
// Attach component to element
this.$.data('_component', this);
// Apply CSS classes and attributes
@@ -3397,7 +3444,7 @@ class Jqhtml_Component {
// Suppressed by _load_only and _load_render_only flags (preloading mode)
if (!this._load_only && !this._load_render_only) {
await this._call_lifecycle('on_loaded');
this.trigger('on_loaded');
this.trigger('loaded');
}
});
return data_changed;
@@ -3418,7 +3465,8 @@ class Jqhtml_Component {
// Don't await - on_create MUST be sync. The warning is enough.
}
// Detect detached elements — skip cache and initial render for elements not in DOM
this._is_detached = !this.$[0].isConnected;
// _force_initial_render overrides this optimization
this._is_detached = !this.$[0].isConnected && !this._force_initial_render;
// OPTIMIZATION: Skip cache operations and snapshot if no custom on_load()
// Components without on_load() don't fetch data, so nothing to cache or restore
if (this.__has_custom_on_load) {
@@ -3464,7 +3512,7 @@ class Jqhtml_Component {
this.trigger('load');
if (!this._load_only && !this._load_render_only) {
await this._call_lifecycle('on_loaded');
this.trigger('on_loaded');
this.trigger('loaded');
}
return;
}
@@ -3544,7 +3592,7 @@ class Jqhtml_Component {
this.trigger('load');
if (!this._load_only && !this._load_render_only) {
await this._call_lifecycle('on_loaded');
this.trigger('on_loaded');
this.trigger('loaded');
}
return;
}
@@ -3624,7 +3672,7 @@ class Jqhtml_Component {
// Suppressed by _load_only and _load_render_only flags (preloading mode)
if (!this._load_only && !this._load_render_only) {
await this._call_lifecycle('on_loaded');
this.trigger('on_loaded');
this.trigger('loaded');
}
}
finally {
@@ -4081,6 +4129,14 @@ class Jqhtml_Component {
on(event_name, callback) {
return event_on(this, event_name, callback);
}
/**
* Register a callback that fires exactly once - delegates to component-events.ts
* If the event already occurred, fires immediately and does not register.
* @see component-events.ts for full documentation
*/
once(event_name, callback) {
return event_once(this, event_name, callback);
}
/**
* Trigger a lifecycle event - delegates to component-events.ts
* @see component-events.ts for full documentation
@@ -5281,7 +5337,7 @@ function init(jQuery) {
}
}
// Version - will be replaced during build with actual version from package.json
const version = '2.3.39';
const version = '2.3.41';
// Default export with all functionality
const jqhtml = {
// Core

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
{
"name": "@jqhtml/core",
"version": "2.3.39",
"version": "2.3.41",
"description": "Core runtime library for JQHTML",
"type": "module",
"main": "./dist/index.js",

View File

@@ -1385,7 +1385,7 @@ export class CodeGenerator {
for (const [name, component] of this.components) {
code += `// Component: ${name}\n`;
code += `jqhtml_components.set('${name}', {\n`;
code += ` _jqhtml_version: '2.3.39',\n`; // Version will be replaced during build
code += ` _jqhtml_version: '2.3.41',\n`; // Version will be replaced during build
code += ` name: '${name}',\n`;
code += ` tag: '${component.tagName}',\n`;
code += ` defaultAttributes: ${this.serializeAttributeObject(component.defaultAttributes)},\n`;

View File

@@ -1,6 +1,6 @@
{
"name": "@jqhtml/parser",
"version": "2.3.39",
"version": "2.3.41",
"description": "JQHTML template parser - converts templates to JavaScript",
"type": "module",
"main": "dist/index.js",

View File

@@ -1,6 +1,6 @@
{
"name": "@jqhtml/ssr",
"version": "2.3.39",
"version": "2.3.41",
"description": "Server-Side Rendering for JQHTML components - renders components to HTML for SEO",
"main": "src/index.js",
"bin": {

View File

@@ -1 +1 @@
2.3.39
2.3.41

View File

@@ -2,7 +2,7 @@
"name": "@jqhtml/vscode-extension",
"displayName": "JQHTML",
"description": "Syntax highlighting and language support for JQHTML template files",
"version": "2.3.39",
"version": "2.3.41",
"publisher": "jqhtml",
"license": "MIT",
"publishConfig": {

24
package-lock.json generated
View File

@@ -2676,9 +2676,9 @@
}
},
"node_modules/@jqhtml/core": {
"version": "2.3.39",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/core/-/core-2.3.39.tgz",
"integrity": "sha512-qyxOBcoFCaf35etqvNOSJppqT4WQLfD9O2b8bAv5la4oSpRUmXSjVJFdv3cSMIK8qClXbupN8bm4FLbAalJqog==",
"version": "2.3.41",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/core/-/core-2.3.41.tgz",
"integrity": "sha512-Owf8Rf7yjG+WSRCPTXtTg+pFpWbTB+MnB/g2Clo6rVWZ5JxEqFZfmKIDx6lSX30pz16ph3RShe9Ijjc8V89S3w==",
"license": "MIT",
"dependencies": {
"@rollup/plugin-node-resolve": "^16.0.1",
@@ -2702,9 +2702,9 @@
}
},
"node_modules/@jqhtml/parser": {
"version": "2.3.39",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/parser/-/parser-2.3.39.tgz",
"integrity": "sha512-DLPwZf1X7enf2lVOaFaIWlu8vQYMgk/+Lioup2w4F07oXFx2+MnFgcJ/Ie9Pf6VUnMT1IOIZQxOd/5QugwFFDA==",
"version": "2.3.41",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/parser/-/parser-2.3.41.tgz",
"integrity": "sha512-q6pT+eqWQf0qEgxzb61nERro5NkIeBnu/DQPUqRNZdywAqam8AHYlwzA5n54BlghJ6m/61DVeRMSHoVu1UV6lA==",
"license": "MIT",
"dependencies": {
"@types/jest": "^29.5.11",
@@ -2742,9 +2742,9 @@
}
},
"node_modules/@jqhtml/ssr": {
"version": "2.3.39",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/ssr/-/ssr-2.3.39.tgz",
"integrity": "sha512-//MaIub8tel8w6l3AiqvoW021Aj9JR8BlVrZsezAO7svAIgsMFTeFdLKUud1+rg8I5Nxe4DE8CiGHz+f3Ts0kA==",
"version": "2.3.41",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/ssr/-/ssr-2.3.41.tgz",
"integrity": "sha512-9uNQ7QaaBBU49ncEKxv9uoajfxe3/vt1wLOMrex81oqKB1PHFIkfQbQ1QcNakYgDTXMFkXKinH0O3qEROH9Lxw==",
"license": "MIT",
"dependencies": {
"jquery": "^3.7.1",
@@ -2838,9 +2838,9 @@
}
},
"node_modules/@jqhtml/vscode-extension": {
"version": "2.3.39",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/vscode-extension/-/vscode-extension-2.3.39.tgz",
"integrity": "sha512-Zi0iS5/t+5IhQoZP54J1/OOFB2OdoM6TM3g37SMJmPKjIDBUt883M3POszKFJwfj8+lrBV5OeJPOmPu3m9RYOQ==",
"version": "2.3.41",
"resolved": "http://npm.internal.hanson.xyz/@jqhtml/vscode-extension/-/vscode-extension-2.3.41.tgz",
"integrity": "sha512-CB3tIppMT3cVLiOIAAxymMtLAae2FJfkf6aFSkQOiONK47h10k2/QkkXFJwXyRRnzbw+ijuhBCDodiLlJtt8aw==",
"license": "MIT",
"engines": {
"vscode": "^1.74.0"