@jqhtml/core 2.3.71 → 2.3.74
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/component.d.ts +54 -0
- package/dist/component.d.ts.map +1 -1
- package/dist/dom-attachment.d.ts +31 -0
- package/dist/dom-attachment.d.ts.map +1 -0
- package/dist/index.cjs +258 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +257 -62
- package/dist/index.js.map +1 -1
- package/dist/jqhtml-core.esm.js +258 -63
- package/dist/jqhtml-core.esm.js.map +1 -1
- package/dist/jquery-plugin.d.ts.map +1 -1
- package/dist/lifecycle-manager.d.ts +0 -5
- package/dist/lifecycle-manager.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -39,6 +39,8 @@ export { Jqhtml_Local_Storage, register_cache_class };
|
|
|
39
39
|
export type { CacheMode, Cache_Class_Options } from './local-storage.js';
|
|
40
40
|
import { Load_Coordinator } from './load-coordinator.js';
|
|
41
41
|
export { Load_Coordinator };
|
|
42
|
+
import { tracked_attachment_count, attachment_observer_active } from './dom-attachment.js';
|
|
43
|
+
export { tracked_attachment_count, attachment_observer_active };
|
|
42
44
|
import { start_data_capture, get_captured_data, stop_data_capture, set_preload_data, clear_preload_data } from './preload-data.js';
|
|
43
45
|
export { start_data_capture, get_captured_data, stop_data_capture, set_preload_data, clear_preload_data };
|
|
44
46
|
export type { PreloadEntry } from './preload-data.js';
|
|
@@ -118,6 +120,8 @@ declare const jqhtml: {
|
|
|
118
120
|
stop_data_capture: typeof stop_data_capture;
|
|
119
121
|
set_preload_data: typeof set_preload_data;
|
|
120
122
|
clear_preload_data: typeof clear_preload_data;
|
|
123
|
+
tracked_attachment_count: typeof tracked_attachment_count;
|
|
124
|
+
attachment_observer_active: typeof attachment_observer_active;
|
|
121
125
|
};
|
|
122
126
|
export default jqhtml;
|
|
123
127
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG7D,OAAO,EACL,QAAQ,EACR,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACnB,wBAAwB,EACxB,eAAe,EAChB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC1G,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7H,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC5F,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAG5F,OAAO,EACL,oBAAoB,EACpB,aAAa,EACd,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,WAAW,EACX,cAAc,EACd,oBAAoB,EACpB,eAAe,EAChB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACL,WAAW,EACX,iBAAiB,EAClB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EACL,YAAY,EACZ,eAAe,EACf,WAAW,EACX,cAAc,EACd,aAAa,EACb,sBAAsB,EACtB,oBAAoB,EACpB,OAAO,EACR,MAAM,YAAY,CAAC;AAMpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG9D,wBAAgB,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,IAAI,CAa/D;AAID,OAAO,EAAE,gBAAgB,IAAI,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAGrF,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EACL,QAAQ,EACR,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,aAAa,EACb,mBAAmB,EACnB,wBAAwB,EACxB,eAAe,EAChB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EACL,oBAAoB,EACpB,aAAa,EACd,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,WAAW,EACX,iBAAiB,EAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,OAAO,oBAAoB,CAAC;AAG5B,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,CAAC;AACtD,YAAY,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAGzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAG5B,OAAO,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAC3F,OAAO,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,CAAC;AAGhE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;AAC1G,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD,eAAO,MAAM,OAAO,gBAAgB,CAAC;AAGrC,MAAM,WAAW,aAAa;IAE5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAG7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAG/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IAGF,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAGD,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAmDL,aAAa,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE;+BAGhC,aAAa;4BAIjB,OAAO,GAAG,MAAM;;;;;6BAuDd,MAAM,eAAc,MAAM,GAAG,MAAM;;;;;;;;;;;CA2B7D,CAAC;AAgCF,eAAe,MAAM,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -214,12 +214,17 @@ class LifecycleManager {
|
|
|
214
214
|
return LifecycleManager.instance;
|
|
215
215
|
}
|
|
216
216
|
constructor() {
|
|
217
|
-
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
//
|
|
217
|
+
// Components stop explicitly via:
|
|
218
|
+
// 1. Parent component re-render (stops descendants before clearing innerHTML)
|
|
219
|
+
// 2. Any jQuery removal that reaches jQuery.cleanData (.remove(), .empty(),
|
|
220
|
+
// .html(x), .text(x), .replaceWith(), .replaceAll()) - hooked in jquery-plugin.ts
|
|
221
221
|
// 3. Explicit .stop() call
|
|
222
|
-
//
|
|
222
|
+
// Native DOM removal is NOT observed for stop; 'detach' (dom-attachment.ts) is the
|
|
223
|
+
// signal for that. Moving a component within the document never stops it.
|
|
224
|
+
//
|
|
225
|
+
// There is deliberately no registry of live components here. The DOM (via
|
|
226
|
+
// element.data('_component')) is the only owner; a registry would pin every
|
|
227
|
+
// component that left the document without being stopped.
|
|
223
228
|
}
|
|
224
229
|
/**
|
|
225
230
|
* Boot a component - run its full lifecycle
|
|
@@ -230,7 +235,6 @@ class LifecycleManager {
|
|
|
230
235
|
* - _load_render_only: on_create + render + on_load + re-render. No on_render, no on_loaded, no on_ready.
|
|
231
236
|
*/
|
|
232
237
|
async boot_component(component) {
|
|
233
|
-
this.active_components.add(component);
|
|
234
238
|
try {
|
|
235
239
|
// Create phase - SYNCHRONOUS, runs BEFORE first render
|
|
236
240
|
component.create();
|
|
@@ -391,12 +395,6 @@ class LifecycleManager {
|
|
|
391
395
|
}
|
|
392
396
|
}
|
|
393
397
|
}
|
|
394
|
-
/**
|
|
395
|
-
* Unregister a component (called on destroy)
|
|
396
|
-
*/
|
|
397
|
-
unregister_component(component) {
|
|
398
|
-
this.active_components.delete(component);
|
|
399
|
-
}
|
|
400
398
|
}
|
|
401
399
|
|
|
402
400
|
/**
|
|
@@ -1615,7 +1613,7 @@ function serialize_for_cache_key(value) {
|
|
|
1615
1613
|
const class_registry = Object.create(null);
|
|
1616
1614
|
// Markers for serialized class instances (unique to avoid collisions with user data)
|
|
1617
1615
|
// Replaced at build time by rollup (see rollup.config.js).
|
|
1618
|
-
const CORE_VERSION = '2.3.
|
|
1616
|
+
const CORE_VERSION = '2.3.74';
|
|
1619
1617
|
const CLASS_MARKER = '__jqhtml_class__';
|
|
1620
1618
|
const PROPS_MARKER = '__jqhtml_props__';
|
|
1621
1619
|
/**
|
|
@@ -3176,6 +3174,85 @@ async function execute_on_load_detached(component, dedup_key = null) {
|
|
|
3176
3174
|
};
|
|
3177
3175
|
}
|
|
3178
3176
|
|
|
3177
|
+
/**
|
|
3178
|
+
* JQHTML DOM Attachment Tracking
|
|
3179
|
+
*
|
|
3180
|
+
* Backs the component 'attach' / 'detach' lifecycle events.
|
|
3181
|
+
*
|
|
3182
|
+
* One document-level MutationObserver (childList + subtree) is installed the first
|
|
3183
|
+
* time any component expresses interest in attachment, and disconnected when the
|
|
3184
|
+
* last interested component is stopped or collected. The observer never inspects
|
|
3185
|
+
* mutation records: it is only a "the tree changed" tick. On each batch it walks
|
|
3186
|
+
* the tracked components and asks each to compare its root's isConnected against
|
|
3187
|
+
* its own recorded attachment state (Jqhtml_Component._attachment_check()). Cost is
|
|
3188
|
+
* O(tracked components) per mutation batch, independent of how much of the page
|
|
3189
|
+
* changed, and zero when nothing has opted in.
|
|
3190
|
+
*
|
|
3191
|
+
* Because MutationObserver delivers per microtask, a node moved synchronously
|
|
3192
|
+
* (remove + insert in one task, e.g. appendTo) never shows a transition. Only a
|
|
3193
|
+
* component whose root is actually off-document when the batch flushes is detached.
|
|
3194
|
+
*
|
|
3195
|
+
* Tracked components are held by WeakRef. A component that is removed from the
|
|
3196
|
+
* document natively (never stopped) and then dropped by everything else is therefore
|
|
3197
|
+
* collectable: the tracker pins nothing. Dead refs are pruned on the next batch.
|
|
3198
|
+
*/
|
|
3199
|
+
const tracked = new Set();
|
|
3200
|
+
const ref_of = new WeakMap();
|
|
3201
|
+
let observer = null;
|
|
3202
|
+
function on_mutation() {
|
|
3203
|
+
for (const ref of tracked) {
|
|
3204
|
+
const component = ref.deref();
|
|
3205
|
+
if (!component || component._stopped) {
|
|
3206
|
+
tracked.delete(ref);
|
|
3207
|
+
continue;
|
|
3208
|
+
}
|
|
3209
|
+
component._attachment_check();
|
|
3210
|
+
}
|
|
3211
|
+
if (tracked.size === 0)
|
|
3212
|
+
disconnect();
|
|
3213
|
+
}
|
|
3214
|
+
function connect() {
|
|
3215
|
+
if (observer !== null)
|
|
3216
|
+
return;
|
|
3217
|
+
if (typeof MutationObserver === 'undefined' || typeof document === 'undefined')
|
|
3218
|
+
return;
|
|
3219
|
+
observer = new MutationObserver(on_mutation);
|
|
3220
|
+
observer.observe(document.documentElement, { childList: true, subtree: true });
|
|
3221
|
+
}
|
|
3222
|
+
function disconnect() {
|
|
3223
|
+
if (observer === null)
|
|
3224
|
+
return;
|
|
3225
|
+
observer.disconnect();
|
|
3226
|
+
observer = null;
|
|
3227
|
+
}
|
|
3228
|
+
/** Start watching a component's root for attach/detach transitions. Idempotent. */
|
|
3229
|
+
function track_attachment(component) {
|
|
3230
|
+
if (ref_of.has(component))
|
|
3231
|
+
return;
|
|
3232
|
+
const ref = new WeakRef(component);
|
|
3233
|
+
ref_of.set(component, ref);
|
|
3234
|
+
tracked.add(ref);
|
|
3235
|
+
connect();
|
|
3236
|
+
}
|
|
3237
|
+
/** Stop watching a component (called from _stop()). Idempotent. */
|
|
3238
|
+
function untrack_attachment(component) {
|
|
3239
|
+
const ref = ref_of.get(component);
|
|
3240
|
+
if (!ref)
|
|
3241
|
+
return;
|
|
3242
|
+
ref_of.delete(component);
|
|
3243
|
+
tracked.delete(ref);
|
|
3244
|
+
if (tracked.size === 0)
|
|
3245
|
+
disconnect();
|
|
3246
|
+
}
|
|
3247
|
+
/** Number of components currently tracked (diagnostics / tests). */
|
|
3248
|
+
function tracked_attachment_count() {
|
|
3249
|
+
return tracked.size;
|
|
3250
|
+
}
|
|
3251
|
+
/** Whether the document observer is currently installed (diagnostics / tests). */
|
|
3252
|
+
function attachment_observer_active() {
|
|
3253
|
+
return observer !== null;
|
|
3254
|
+
}
|
|
3255
|
+
|
|
3179
3256
|
/**
|
|
3180
3257
|
* JQHTML Component Cache Integration
|
|
3181
3258
|
*
|
|
@@ -4084,6 +4161,12 @@ class Jqhtml_Component {
|
|
|
4084
4161
|
this.__load_gates = []; // Pending gates (cleared once the first load begins)
|
|
4085
4162
|
this.__first_load_started = false; // Latch: true once the first load phase begins (enforces one-shot + throw-after)
|
|
4086
4163
|
this.__gate_resume = null; // Resolver to release an in-progress gate wait early (reload/refresh/stop)
|
|
4164
|
+
// DOM attachment state machine - see _attachment_check() / dom-attachment.ts.
|
|
4165
|
+
// _attached is the component's OWN belief about whether it is in the document;
|
|
4166
|
+
// it flips at most once per direction, and 'attach' / 'detach' fire only on a flip.
|
|
4167
|
+
this._attached = false;
|
|
4168
|
+
this._attachment_checked = false; // First check has run (after the first 'ready' dispatch)
|
|
4169
|
+
this._attachment_tracking = false; // Something is interested: on_attach/on_detach overridden, or .on('attach'|'detach')
|
|
4087
4170
|
// Detect custom on_load() override immediately
|
|
4088
4171
|
// Prototype chain is set up before constructor runs, so this.on_load
|
|
4089
4172
|
// correctly resolves to child class override if one exists
|
|
@@ -4157,6 +4240,12 @@ class Jqhtml_Component {
|
|
|
4157
4240
|
// Initialize this.state as an empty object (convention for arbitrary component state)
|
|
4158
4241
|
// No special meaning to framework - mutable anywhere, not cached, not frozen
|
|
4159
4242
|
this.state = {};
|
|
4243
|
+
// Overriding on_attach()/on_detach() is interest in attachment tracking. Tracking
|
|
4244
|
+
// itself only starts after the first 'ready' dispatch (see _attachment_check()).
|
|
4245
|
+
if (this.on_attach !== Jqhtml_Component.prototype.on_attach ||
|
|
4246
|
+
this.on_detach !== Jqhtml_Component.prototype.on_detach) {
|
|
4247
|
+
this._attachment_tracking = true;
|
|
4248
|
+
}
|
|
4160
4249
|
this._log_lifecycle('construct', 'complete');
|
|
4161
4250
|
}
|
|
4162
4251
|
/**
|
|
@@ -4170,7 +4259,9 @@ class Jqhtml_Component {
|
|
|
4170
4259
|
on_render: 'Use render() to trigger a re-render.',
|
|
4171
4260
|
on_load: 'Use reload() to refresh data.',
|
|
4172
4261
|
on_ready: 'Called automatically when ready.',
|
|
4173
|
-
on_stop: 'Use stop() to stop the component.'
|
|
4262
|
+
on_stop: 'Use stop() to stop the component.',
|
|
4263
|
+
on_attach: 'Called automatically when the component enters the document.',
|
|
4264
|
+
on_detach: 'Called automatically when the component leaves the document.'
|
|
4174
4265
|
};
|
|
4175
4266
|
const impls = {};
|
|
4176
4267
|
const self = this;
|
|
@@ -5524,8 +5615,13 @@ class Jqhtml_Component {
|
|
|
5524
5615
|
// stopped children into the parent's registry.
|
|
5525
5616
|
this._log_lifecycle('destroy', 'start');
|
|
5526
5617
|
this.$.addClass('_Component_Stopped');
|
|
5527
|
-
//
|
|
5528
|
-
|
|
5618
|
+
// A component that believes it is attached is detached first, so 'detach' always
|
|
5619
|
+
// precedes 'stop' and subscribers can rely on strict attach/detach alternation.
|
|
5620
|
+
// A component that never fired 'attach' (stopped before ready, or born and kept
|
|
5621
|
+
// off-document) fires no 'detach' either. Either way it leaves the tracker.
|
|
5622
|
+
if (this._attached)
|
|
5623
|
+
this._transition_attachment(false);
|
|
5624
|
+
untrack_attachment(this);
|
|
5529
5625
|
// Call user's on_stop() hook with authorization (sync) - only when actually
|
|
5530
5626
|
// overridden, since _call_lifecycle_sync() on the base no-op costs per child
|
|
5531
5627
|
// on every re-render.
|
|
@@ -5570,6 +5666,94 @@ class Jqhtml_Component {
|
|
|
5570
5666
|
on_loaded() { } // Override to process loaded data (e.g., clone this.data to this.state)
|
|
5571
5667
|
async on_ready() { }
|
|
5572
5668
|
on_stop() { }
|
|
5669
|
+
on_attach() { } // Sync. Root entered the document (first checked after 'ready')
|
|
5670
|
+
on_detach() { } // Sync. Root left the document, or the component is being stopped while attached
|
|
5671
|
+
// -------------------------------------------------------------------------
|
|
5672
|
+
// DOM attachment state machine
|
|
5673
|
+
// -------------------------------------------------------------------------
|
|
5674
|
+
/**
|
|
5675
|
+
* Whether this component's root is in the document right now.
|
|
5676
|
+
*
|
|
5677
|
+
* A live answer - one isConnected read - so it is correct at every point in the
|
|
5678
|
+
* lifecycle (including on_create()/on_load()/on_ready(), before the first 'attach')
|
|
5679
|
+
* and for untracked components (a natively-removed component that nothing watches
|
|
5680
|
+
* still answers false). A stopped component always answers false.
|
|
5681
|
+
*
|
|
5682
|
+
* It does NOT read the recorded state behind 'attach'/'detach' (_attached), and it
|
|
5683
|
+
* never starts tracking. The two can disagree briefly: is_attached() can be true
|
|
5684
|
+
* before the first 'attach' has fired, and changes a moment before the matching
|
|
5685
|
+
* event, since the events come from the document observer.
|
|
5686
|
+
*/
|
|
5687
|
+
is_attached() {
|
|
5688
|
+
return !this._stopped && !!this.$[0].isConnected;
|
|
5689
|
+
}
|
|
5690
|
+
/**
|
|
5691
|
+
* Flip the recorded state and fire the matching hook + event. The opposite
|
|
5692
|
+
* sticky event is invalidated first, so a late subscriber only ever sees the
|
|
5693
|
+
* current state. Hook errors are isolated; the event still fires.
|
|
5694
|
+
* @private
|
|
5695
|
+
*/
|
|
5696
|
+
_transition_attachment(attached) {
|
|
5697
|
+
this._attached = attached;
|
|
5698
|
+
const event_name = attached ? 'attach' : 'detach';
|
|
5699
|
+
const hook_name = attached ? 'on_attach' : 'on_detach';
|
|
5700
|
+
this.invalidate(attached ? 'detach' : 'attach');
|
|
5701
|
+
if (this[hook_name] !== Jqhtml_Component.prototype[hook_name]) {
|
|
5702
|
+
try {
|
|
5703
|
+
const result = this._call_lifecycle_sync(hook_name);
|
|
5704
|
+
if (result && typeof result.then === 'function') {
|
|
5705
|
+
console.warn(`[JQHTML] Component "${this.component_name()}" returned a Promise from ${hook_name}(). ` +
|
|
5706
|
+
`${hook_name}() must be synchronous code. Remove 'async' from the function declaration.`);
|
|
5707
|
+
}
|
|
5708
|
+
}
|
|
5709
|
+
catch (error) {
|
|
5710
|
+
console.error(`[JQHTML] Error in ${hook_name}() for ${this.component_name()}:`, error);
|
|
5711
|
+
}
|
|
5712
|
+
}
|
|
5713
|
+
this.trigger(event_name);
|
|
5714
|
+
}
|
|
5715
|
+
/**
|
|
5716
|
+
* Compare the root's live connectivity with the recorded state and transition
|
|
5717
|
+
* on a difference. Idempotent. Called by the document observer on every
|
|
5718
|
+
* mutation batch for tracked components, and directly by the framework after
|
|
5719
|
+
* 'ready' and when interest is registered late.
|
|
5720
|
+
* @private
|
|
5721
|
+
*/
|
|
5722
|
+
_attachment_check() {
|
|
5723
|
+
if (this._stopped)
|
|
5724
|
+
return;
|
|
5725
|
+
const connected = !!this.$[0].isConnected;
|
|
5726
|
+
if (connected !== this._attached)
|
|
5727
|
+
this._transition_attachment(connected);
|
|
5728
|
+
}
|
|
5729
|
+
/**
|
|
5730
|
+
* The first check, run once the 'ready' handlers have completed. Fires 'attach'
|
|
5731
|
+
* if the component was born attached, even with no listener, so a later
|
|
5732
|
+
* .on('attach') gets the sticky fire. Deferred interest starts tracking here.
|
|
5733
|
+
* @private
|
|
5734
|
+
*/
|
|
5735
|
+
_attachment_first_check() {
|
|
5736
|
+
const first = !this._attachment_checked;
|
|
5737
|
+
this._attachment_checked = true;
|
|
5738
|
+
this._attachment_check();
|
|
5739
|
+
if (first && this._attachment_tracking)
|
|
5740
|
+
track_attachment(this);
|
|
5741
|
+
}
|
|
5742
|
+
/**
|
|
5743
|
+
* Register interest in attach/detach. Before the first ready check this only
|
|
5744
|
+
* records the interest; after it, tracking starts immediately and a check runs
|
|
5745
|
+
* at once, so a late subscriber on a natively-removed component sees 'detach'.
|
|
5746
|
+
* @private
|
|
5747
|
+
*/
|
|
5748
|
+
_watch_attachment() {
|
|
5749
|
+
if (this._attachment_tracking)
|
|
5750
|
+
return;
|
|
5751
|
+
this._attachment_tracking = true;
|
|
5752
|
+
if (this._attachment_checked && !this._stopped) {
|
|
5753
|
+
track_attachment(this);
|
|
5754
|
+
this._attachment_check();
|
|
5755
|
+
}
|
|
5756
|
+
}
|
|
5573
5757
|
/**
|
|
5574
5758
|
* Called with the viewport width in CSS pixels:
|
|
5575
5759
|
* - after every on_render()
|
|
@@ -5634,6 +5818,8 @@ class Jqhtml_Component {
|
|
|
5634
5818
|
* @see component-events.ts for full documentation
|
|
5635
5819
|
*/
|
|
5636
5820
|
on(event_name, callback) {
|
|
5821
|
+
if (event_name === 'attach' || event_name === 'detach')
|
|
5822
|
+
this._watch_attachment();
|
|
5637
5823
|
return event_on(this, event_name, callback);
|
|
5638
5824
|
}
|
|
5639
5825
|
/**
|
|
@@ -5642,14 +5828,24 @@ class Jqhtml_Component {
|
|
|
5642
5828
|
* @see component-events.ts for full documentation
|
|
5643
5829
|
*/
|
|
5644
5830
|
once(event_name, callback) {
|
|
5831
|
+
if (event_name === 'attach' || event_name === 'detach')
|
|
5832
|
+
this._watch_attachment();
|
|
5645
5833
|
return event_once(this, event_name, callback);
|
|
5646
5834
|
}
|
|
5647
5835
|
/**
|
|
5648
5836
|
* Trigger a lifecycle event - delegates to component-events.ts
|
|
5649
5837
|
* @see component-events.ts for full documentation
|
|
5838
|
+
*
|
|
5839
|
+
* 'ready' is special: once its handlers have run, the component runs its first
|
|
5840
|
+
* attachment check (and every later one, idempotently). Doing it here rather than
|
|
5841
|
+
* at each of the call sites that trigger 'ready' guarantees the order
|
|
5842
|
+
* on_ready() -> 'ready' handlers -> 'attach', so everything on_ready() set up is
|
|
5843
|
+
* complete before anyone learns the component is in the document.
|
|
5650
5844
|
*/
|
|
5651
5845
|
trigger(event_name, data) {
|
|
5652
5846
|
event_trigger(this, event_name, data);
|
|
5847
|
+
if (event_name === 'ready' && !this._stopped)
|
|
5848
|
+
this._attachment_first_check();
|
|
5653
5849
|
}
|
|
5654
5850
|
/**
|
|
5655
5851
|
* Check if any callbacks are registered for a given event
|
|
@@ -7083,9 +7279,42 @@ function init_jquery_plugin(jQuery) {
|
|
|
7083
7279
|
return jQuery(results);
|
|
7084
7280
|
};
|
|
7085
7281
|
// Store original jQuery methods
|
|
7086
|
-
const originalEmpty = jQuery.fn.empty;
|
|
7087
7282
|
const originalHtml = jQuery.fn.html;
|
|
7088
|
-
|
|
7283
|
+
// ---------------------------------------------------------------------------
|
|
7284
|
+
// Stop components on every jQuery-driven removal by hooking jQuery.cleanData.
|
|
7285
|
+
//
|
|
7286
|
+
// jQuery routes .remove(), .empty(), .html(x), .text(x), .replaceWith() and
|
|
7287
|
+
// .replaceAll() through jQuery.cleanData(elems) to drop the data store and
|
|
7288
|
+
// handlers of every element about to leave the tree - and `elems` is already the
|
|
7289
|
+
// flattened subtree, in document order (parent before child). Stopping here is
|
|
7290
|
+
// therefore one classList check per removed element, no extra traversal, and
|
|
7291
|
+
// covers every jQuery removal path at once. It is the same hook jQuery UI's
|
|
7292
|
+
// widget factory uses for the same reason.
|
|
7293
|
+
//
|
|
7294
|
+
// It MUST be installed on the original jQuery object: jQuery's own code calls
|
|
7295
|
+
// cleanData through its closure-local reference, not through our wrapper. The
|
|
7296
|
+
// wrapper's copied static is updated below so both names agree.
|
|
7297
|
+
//
|
|
7298
|
+
// .detach() does NOT call cleanData, by jQuery's own design (it keeps data for
|
|
7299
|
+
// reinsertion), and native DOM removal (el.remove(), innerHTML = '') bypasses
|
|
7300
|
+
// jQuery entirely. Neither stops a component; the 'detach' lifecycle event is
|
|
7301
|
+
// the signal for those. Moving a component (.appendTo) is not a removal.
|
|
7302
|
+
// ---------------------------------------------------------------------------
|
|
7303
|
+
const originalCleanData = _jqhtml_original_jquery.cleanData;
|
|
7304
|
+
const cleanDataWithComponentStop = function (elems) {
|
|
7305
|
+
for (let i = 0; i < elems.length; i++) {
|
|
7306
|
+
const el = elems[i];
|
|
7307
|
+
if (el.nodeType !== 1 || !el.classList.contains('Component'))
|
|
7308
|
+
continue;
|
|
7309
|
+
const component = _jqhtml_original_jquery.data(el, '_component');
|
|
7310
|
+
if (component && !component._stopped) {
|
|
7311
|
+
component._stop(); // Not recursive: every descendant is in elems too
|
|
7312
|
+
}
|
|
7313
|
+
}
|
|
7314
|
+
return originalCleanData(elems);
|
|
7315
|
+
};
|
|
7316
|
+
_jqhtml_original_jquery.cleanData = cleanDataWithComponentStop;
|
|
7317
|
+
jQuery.cleanData = cleanDataWithComponentStop;
|
|
7089
7318
|
// ---------------------------------------------------------------------------
|
|
7090
7319
|
// Guard against hand-creating elements with data-sid via jQuery.
|
|
7091
7320
|
//
|
|
@@ -7142,53 +7371,15 @@ function init_jquery_plugin(jQuery) {
|
|
|
7142
7371
|
` • <div class="MyComponent__${sid}"> → .find('.MyComponent__${sid}')`);
|
|
7143
7372
|
};
|
|
7144
7373
|
/**
|
|
7145
|
-
* Override jQuery.fn.
|
|
7146
|
-
*
|
|
7147
|
-
*/
|
|
7148
|
-
jQuery.fn.empty = function () {
|
|
7149
|
-
return this.each(function () {
|
|
7150
|
-
// Stop all child components before clearing DOM
|
|
7151
|
-
jQuery(this).find('.Component').each(function () {
|
|
7152
|
-
const component = jQuery(this).data('_component');
|
|
7153
|
-
if (component && !component._stopped) {
|
|
7154
|
-
component._stop(); // Stop just the component, DOM will be cleared anyway
|
|
7155
|
-
}
|
|
7156
|
-
});
|
|
7157
|
-
// Call original empty
|
|
7158
|
-
originalEmpty.call(jQuery(this));
|
|
7159
|
-
});
|
|
7160
|
-
};
|
|
7161
|
-
/**
|
|
7162
|
-
* Override jQuery.fn.html() to stop child components when setting new content
|
|
7163
|
-
* When used as setter, calls .empty() first to properly cleanup components
|
|
7374
|
+
* Override jQuery.fn.html() setter to reject hand-written data-sid before the
|
|
7375
|
+
* DOM is mutated. Component stopping is handled by the cleanData hook above.
|
|
7164
7376
|
*/
|
|
7165
7377
|
jQuery.fn.html = function (value) {
|
|
7166
|
-
// Getter - just pass through
|
|
7167
7378
|
if (arguments.length === 0) {
|
|
7168
7379
|
return originalHtml.call(this);
|
|
7169
7380
|
}
|
|
7170
|
-
// Reject hand-written data-sid before mutating the DOM
|
|
7171
7381
|
assert_no_manual_sid(value, '.html()');
|
|
7172
|
-
|
|
7173
|
-
return this.each(function () {
|
|
7174
|
-
jQuery(this).empty();
|
|
7175
|
-
originalHtml.call(jQuery(this), value);
|
|
7176
|
-
});
|
|
7177
|
-
};
|
|
7178
|
-
/**
|
|
7179
|
-
* Override jQuery.fn.text() to stop child components when setting new content
|
|
7180
|
-
* When used as setter, calls .empty() first to properly cleanup components
|
|
7181
|
-
*/
|
|
7182
|
-
jQuery.fn.text = function (value) {
|
|
7183
|
-
// Getter - just pass through
|
|
7184
|
-
if (arguments.length === 0) {
|
|
7185
|
-
return originalText.call(this);
|
|
7186
|
-
}
|
|
7187
|
-
// Setter - empty first (which stops components), then set content
|
|
7188
|
-
return this.each(function () {
|
|
7189
|
-
jQuery(this).empty();
|
|
7190
|
-
originalText.call(jQuery(this), value);
|
|
7191
|
-
});
|
|
7382
|
+
return originalHtml.call(this, value);
|
|
7192
7383
|
};
|
|
7193
7384
|
// Store original jQuery.fn.on
|
|
7194
7385
|
const originalOn = jQuery.fn.on;
|
|
@@ -7330,7 +7521,7 @@ function init(jQuery, config) {
|
|
|
7330
7521
|
}
|
|
7331
7522
|
}
|
|
7332
7523
|
// Version - will be replaced during build with actual version from package.json
|
|
7333
|
-
const version = '2.3.
|
|
7524
|
+
const version = '2.3.74';
|
|
7334
7525
|
// Default export with all functionality
|
|
7335
7526
|
const jqhtml = {
|
|
7336
7527
|
// Core
|
|
@@ -7445,7 +7636,11 @@ const jqhtml = {
|
|
|
7445
7636
|
get_captured_data,
|
|
7446
7637
|
stop_data_capture,
|
|
7447
7638
|
set_preload_data,
|
|
7448
|
-
clear_preload_data
|
|
7639
|
+
clear_preload_data,
|
|
7640
|
+
// Attachment tracking diagnostics - how many components are watched for
|
|
7641
|
+
// attach/detach and whether the document observer is currently installed
|
|
7642
|
+
tracked_attachment_count,
|
|
7643
|
+
attachment_observer_active
|
|
7449
7644
|
};
|
|
7450
7645
|
// Auto-register on window for browser environments
|
|
7451
7646
|
// This is REQUIRED for compiled templates which use window.jqhtml.register_template()
|
|
@@ -7475,5 +7670,5 @@ if (typeof window !== 'undefined' && !window.jqhtml) {
|
|
|
7475
7670
|
}
|
|
7476
7671
|
}
|
|
7477
7672
|
|
|
7478
|
-
export { COMPONENT_NAME_PATTERN, COMPONENT_NAME_RULE, Jqhtml_Component, LifecycleManager as Jqhtml_LifecycleManager, Jqhtml_Local_Storage, LifecycleManager, Load_Coordinator, add_object_printer, applyDebugDelay, boot, clear_preload_data, configure, create_component, debug_overlay, jqhtml as default, devWarn, dynamic_component_name, escape_html, escape_html_nl2br, extract_slots, get_captured_data, get_component_class, get_component_names, get_config, get_object_printers, get_registered_templates, get_template, get_template_by_class, handleComponentError, has_component, init, init_jquery_plugin, isSequentialProcessing, is_component_name, list_components, logDataChange, logDispatch, logInstruction, logLifecycle, print_object, process_instructions, register, register_cache_class, register_component, register_template, set_preload_data, start_data_capture, stop_data_capture, version };
|
|
7673
|
+
export { COMPONENT_NAME_PATTERN, COMPONENT_NAME_RULE, Jqhtml_Component, LifecycleManager as Jqhtml_LifecycleManager, Jqhtml_Local_Storage, LifecycleManager, Load_Coordinator, add_object_printer, applyDebugDelay, attachment_observer_active, boot, clear_preload_data, configure, create_component, debug_overlay, jqhtml as default, devWarn, dynamic_component_name, escape_html, escape_html_nl2br, extract_slots, get_captured_data, get_component_class, get_component_names, get_config, get_object_printers, get_registered_templates, get_template, get_template_by_class, handleComponentError, has_component, init, init_jquery_plugin, isSequentialProcessing, is_component_name, list_components, logDataChange, logDispatch, logInstruction, logLifecycle, print_object, process_instructions, register, register_cache_class, register_component, register_template, set_preload_data, start_data_capture, stop_data_capture, tracked_attachment_count, version };
|
|
7479
7674
|
//# sourceMappingURL=index.js.map
|