@jqhtml/core 2.3.4 → 2.3.6
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 +20 -0
- package/dist/component.d.ts.map +1 -1
- package/dist/debug-entry.d.ts +3 -31
- package/dist/debug-entry.d.ts.map +1 -1
- package/dist/index.cjs +91 -422
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +92 -420
- package/dist/index.js.map +1 -1
- package/dist/jqhtml-core.esm.js +93 -421
- package/dist/jqhtml-core.esm.js.map +1 -1
- package/dist/jqhtml-debug.esm.js +1 -383
- package/dist/jqhtml-debug.esm.js.map +1 -1
- package/package.json +1 -1
- package/dist/debug-overlay.d.ts +0 -61
- package/dist/debug-overlay.d.ts.map +0 -1
package/dist/jqhtml-core.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* JQHTML Core v2.3.
|
|
2
|
+
* JQHTML Core v2.3.6
|
|
3
3
|
* (c) 2025 JQHTML Team
|
|
4
4
|
* Released under the MIT License
|
|
5
5
|
*/
|
|
@@ -884,7 +884,7 @@ function devWarn(message) {
|
|
|
884
884
|
console.warn(`[JQHTML Dev Warning] ${message}`);
|
|
885
885
|
}
|
|
886
886
|
// Get global jqhtml object
|
|
887
|
-
function getJqhtml
|
|
887
|
+
function getJqhtml() {
|
|
888
888
|
if (typeof window !== 'undefined' && window.jqhtml) {
|
|
889
889
|
return window.jqhtml;
|
|
890
890
|
}
|
|
@@ -897,7 +897,7 @@ function getJqhtml$1() {
|
|
|
897
897
|
}
|
|
898
898
|
// Visual flash effect
|
|
899
899
|
function flashComponent(component, eventType) {
|
|
900
|
-
const jqhtml = getJqhtml
|
|
900
|
+
const jqhtml = getJqhtml();
|
|
901
901
|
if (!jqhtml?.debug?.flashComponents)
|
|
902
902
|
return;
|
|
903
903
|
const duration = jqhtml.debug.flashDuration || 500;
|
|
@@ -919,7 +919,7 @@ function flashComponent(component, eventType) {
|
|
|
919
919
|
}
|
|
920
920
|
// Log lifecycle event
|
|
921
921
|
function logLifecycle(component, phase, status) {
|
|
922
|
-
const jqhtml = getJqhtml
|
|
922
|
+
const jqhtml = getJqhtml();
|
|
923
923
|
if (!jqhtml?.debug)
|
|
924
924
|
return;
|
|
925
925
|
const shouldLog = jqhtml.debug.logFullLifecycle ||
|
|
@@ -965,7 +965,7 @@ function logLifecycle(component, phase, status) {
|
|
|
965
965
|
}
|
|
966
966
|
// Apply delays based on lifecycle phase
|
|
967
967
|
function applyDebugDelay(phase) {
|
|
968
|
-
const jqhtml = getJqhtml
|
|
968
|
+
const jqhtml = getJqhtml();
|
|
969
969
|
if (!jqhtml?.debug)
|
|
970
970
|
return;
|
|
971
971
|
let delayMs = 0;
|
|
@@ -986,14 +986,14 @@ function applyDebugDelay(phase) {
|
|
|
986
986
|
}
|
|
987
987
|
// Log instruction processing
|
|
988
988
|
function logInstruction(type, data) {
|
|
989
|
-
const jqhtml = getJqhtml
|
|
989
|
+
const jqhtml = getJqhtml();
|
|
990
990
|
if (!jqhtml?.debug?.logInstructionProcessing)
|
|
991
991
|
return;
|
|
992
992
|
console.log(`[JQHTML Instruction] ${type}:`, data);
|
|
993
993
|
}
|
|
994
994
|
// Log data changes
|
|
995
995
|
function logDataChange(component, property, oldValue, newValue) {
|
|
996
|
-
const jqhtml = getJqhtml
|
|
996
|
+
const jqhtml = getJqhtml();
|
|
997
997
|
if (!jqhtml?.debug?.traceDataFlow)
|
|
998
998
|
return;
|
|
999
999
|
console.log(`[JQHTML Data] ${component.constructor.name}#${component._cid}.data.${property}:`, { old: oldValue, new: newValue });
|
|
@@ -1006,7 +1006,7 @@ function updateComponentTree() {
|
|
|
1006
1006
|
}
|
|
1007
1007
|
// Router dispatch logging
|
|
1008
1008
|
function logDispatch(url, route, params, verbose = false) {
|
|
1009
|
-
const jqhtml = getJqhtml
|
|
1009
|
+
const jqhtml = getJqhtml();
|
|
1010
1010
|
if (!jqhtml?.debug)
|
|
1011
1011
|
return;
|
|
1012
1012
|
const shouldLog = jqhtml.debug.logDispatch || jqhtml.debug.logDispatchVerbose;
|
|
@@ -1028,12 +1028,12 @@ function logDispatch(url, route, params, verbose = false) {
|
|
|
1028
1028
|
}
|
|
1029
1029
|
// Check if sequential processing is enabled
|
|
1030
1030
|
function isSequentialProcessing() {
|
|
1031
|
-
const jqhtml = getJqhtml
|
|
1031
|
+
const jqhtml = getJqhtml();
|
|
1032
1032
|
return jqhtml?.debug?.sequentialProcessing || false;
|
|
1033
1033
|
}
|
|
1034
1034
|
// Error handling with break on error
|
|
1035
1035
|
function handleComponentError(component, phase, error) {
|
|
1036
|
-
const jqhtml = getJqhtml
|
|
1036
|
+
const jqhtml = getJqhtml();
|
|
1037
1037
|
console.error(`[JQHTML Error] ${component.constructor.name}#${component._cid} failed in ${phase}:`, error);
|
|
1038
1038
|
if (jqhtml?.debug?.breakOnError) {
|
|
1039
1039
|
debugger; // This will pause execution in dev tools
|
|
@@ -1061,6 +1061,9 @@ function handleComponentError(component, phase, error) {
|
|
|
1061
1061
|
* - Scoped IDs using _cid pattern
|
|
1062
1062
|
* - Event emission and CSS class hierarchy
|
|
1063
1063
|
*/
|
|
1064
|
+
// WeakMap storage for protected lifecycle method implementations (Option 2)
|
|
1065
|
+
// See docs/internal/lifecycle-method-protection.md for design details
|
|
1066
|
+
const lifecycle_impls = new WeakMap();
|
|
1064
1067
|
class Jqhtml_Component {
|
|
1065
1068
|
constructor(element, args = {}) {
|
|
1066
1069
|
this._ready_state = 0; // 0=created, 1=init, 2=loaded, 3=rendered, 4=ready
|
|
@@ -1081,6 +1084,7 @@ class Jqhtml_Component {
|
|
|
1081
1084
|
this.__initial_data_snapshot = null; // Snapshot of this.data after on_create() for restoration before on_load()
|
|
1082
1085
|
this.__data_frozen = false; // Track if this.data is currently frozen
|
|
1083
1086
|
this.next_reload_force_refresh = null; // State machine for reload()/refresh() debounce precedence
|
|
1087
|
+
this.__lifecycle_authorized = false; // Flag for lifecycle method protection
|
|
1084
1088
|
this._cid = this._generate_cid();
|
|
1085
1089
|
this._lifecycle_manager = LifecycleManager.get_instance();
|
|
1086
1090
|
// Create or wrap element
|
|
@@ -1194,6 +1198,63 @@ class Jqhtml_Component {
|
|
|
1194
1198
|
this.state = {};
|
|
1195
1199
|
this._log_lifecycle('construct', 'complete');
|
|
1196
1200
|
}
|
|
1201
|
+
/**
|
|
1202
|
+
* Protect lifecycle methods from manual invocation
|
|
1203
|
+
* Stores original implementations in WeakMap, replaces with guarded wrappers
|
|
1204
|
+
* @private
|
|
1205
|
+
*/
|
|
1206
|
+
_protect_lifecycle_methods() {
|
|
1207
|
+
const methods = {
|
|
1208
|
+
on_create: 'Called automatically during creation.',
|
|
1209
|
+
on_render: 'Use render() to trigger a re-render.',
|
|
1210
|
+
on_load: 'Use reload() to refresh data.',
|
|
1211
|
+
on_ready: 'Called automatically when ready.',
|
|
1212
|
+
on_stop: 'Use stop() to stop the component.'
|
|
1213
|
+
};
|
|
1214
|
+
const impls = {};
|
|
1215
|
+
const self = this;
|
|
1216
|
+
for (const [name, help] of Object.entries(methods)) {
|
|
1217
|
+
const original = this[name];
|
|
1218
|
+
// Skip if using base class default (empty method)
|
|
1219
|
+
if (original === Jqhtml_Component.prototype[name])
|
|
1220
|
+
continue;
|
|
1221
|
+
impls[name] = original;
|
|
1222
|
+
// Create wrapper with same function name (for stack traces)
|
|
1223
|
+
this[name] = {
|
|
1224
|
+
[name](...args) {
|
|
1225
|
+
if (!self.__lifecycle_authorized) {
|
|
1226
|
+
throw new Error(`[JQHTML] ${name}() cannot be called manually. ${help}\n` +
|
|
1227
|
+
`Component: ${self.component_name()} (_cid: ${self._cid})`);
|
|
1228
|
+
}
|
|
1229
|
+
return lifecycle_impls.get(self)[name].apply(self, args);
|
|
1230
|
+
}
|
|
1231
|
+
}[name];
|
|
1232
|
+
}
|
|
1233
|
+
lifecycle_impls.set(this, impls);
|
|
1234
|
+
}
|
|
1235
|
+
/**
|
|
1236
|
+
* Call a lifecycle method with authorization (async)
|
|
1237
|
+
* Framework calls this to invoke lifecycle methods, bypassing the protection wrapper.
|
|
1238
|
+
* The flag is set momentarily for the wrapper check, then reset BEFORE user code runs.
|
|
1239
|
+
* This ensures any nested lifecycle calls from user code will fail the flag check.
|
|
1240
|
+
* @private
|
|
1241
|
+
*/
|
|
1242
|
+
async _call_lifecycle(name, context) {
|
|
1243
|
+
// Get the original implementation (bypasses wrapper entirely)
|
|
1244
|
+
const impl = lifecycle_impls.get(this)?.[name] || this[name];
|
|
1245
|
+
// Call original directly - no flag needed since we bypass the wrapper
|
|
1246
|
+
return await impl.call(context || this);
|
|
1247
|
+
}
|
|
1248
|
+
/**
|
|
1249
|
+
* Call a lifecycle method with authorization (sync version for sync methods like on_stop)
|
|
1250
|
+
* @private
|
|
1251
|
+
*/
|
|
1252
|
+
_call_lifecycle_sync(name) {
|
|
1253
|
+
// Get the original implementation (bypasses wrapper entirely)
|
|
1254
|
+
const impl = lifecycle_impls.get(this)?.[name] || this[name];
|
|
1255
|
+
// Call original directly - no flag needed since we bypass the wrapper
|
|
1256
|
+
return impl.call(this);
|
|
1257
|
+
}
|
|
1197
1258
|
/**
|
|
1198
1259
|
* Boot - Start the full component lifecycle
|
|
1199
1260
|
* Called immediately after construction by instruction processor
|
|
@@ -1207,6 +1268,8 @@ class Jqhtml_Component {
|
|
|
1207
1268
|
if (this._booted)
|
|
1208
1269
|
return;
|
|
1209
1270
|
this._booted = true;
|
|
1271
|
+
// Protect lifecycle methods from manual invocation (must happen after subclass constructor)
|
|
1272
|
+
this._protect_lifecycle_methods();
|
|
1210
1273
|
await this._lifecycle_manager.boot_component(this);
|
|
1211
1274
|
}
|
|
1212
1275
|
// -------------------------------------------------------------------------
|
|
@@ -1417,9 +1480,9 @@ class Jqhtml_Component {
|
|
|
1417
1480
|
// Don't update ready state here - let phases complete in order
|
|
1418
1481
|
this._update_debug_attrs();
|
|
1419
1482
|
this._log_lifecycle('render', 'complete');
|
|
1420
|
-
// Call on_render() immediately after render completes
|
|
1483
|
+
// Call on_render() with authorization (sync) immediately after render completes
|
|
1421
1484
|
// This ensures event handlers are always re-attached after DOM updates
|
|
1422
|
-
const renderResult = this.on_render
|
|
1485
|
+
const renderResult = this._call_lifecycle_sync('on_render');
|
|
1423
1486
|
if (renderResult && typeof renderResult.then === 'function') {
|
|
1424
1487
|
console.warn(`[JQHTML] Component "${this.component_name()}" returned a Promise from on_render(). ` +
|
|
1425
1488
|
`on_render() must be synchronous code. Remove 'async' from the function declaration.`);
|
|
@@ -1484,8 +1547,8 @@ class Jqhtml_Component {
|
|
|
1484
1547
|
if (this._render_count !== render_id) {
|
|
1485
1548
|
return; // Stale render, don't call on_ready
|
|
1486
1549
|
}
|
|
1487
|
-
// Call on_ready hook
|
|
1488
|
-
await this.on_ready
|
|
1550
|
+
// Call on_ready hook with authorization
|
|
1551
|
+
await this._call_lifecycle('on_ready');
|
|
1489
1552
|
// Trigger ready event
|
|
1490
1553
|
await this.trigger('ready');
|
|
1491
1554
|
})();
|
|
@@ -1505,8 +1568,8 @@ class Jqhtml_Component {
|
|
|
1505
1568
|
if (this._stopped || this._ready_state >= 1)
|
|
1506
1569
|
return;
|
|
1507
1570
|
this._log_lifecycle('create', 'start');
|
|
1508
|
-
// Call on_create() and validate it's synchronous
|
|
1509
|
-
const result = this.on_create
|
|
1571
|
+
// Call on_create() with authorization and validate it's synchronous
|
|
1572
|
+
const result = await this._call_lifecycle('on_create');
|
|
1510
1573
|
if (result && typeof result.then === 'function') {
|
|
1511
1574
|
console.warn(`[JQHTML] Component "${this.component_name()}" returned a Promise from on_create(). ` +
|
|
1512
1575
|
`on_create() must be synchronous code. Remove 'async' from the function declaration.`);
|
|
@@ -1621,8 +1684,8 @@ class Jqhtml_Component {
|
|
|
1621
1684
|
if (window.jqhtml?.debug?.verbose) {
|
|
1622
1685
|
console.log(`[Cache] Component ${this._cid} (${this.component_name()}) has non-serializable args - load deduplication and caching disabled`, { uncacheable_property });
|
|
1623
1686
|
}
|
|
1624
|
-
// Execute on_load() without deduplication or caching
|
|
1625
|
-
await this.on_load
|
|
1687
|
+
// Execute on_load() with authorization, without deduplication or caching
|
|
1688
|
+
await this._call_lifecycle('on_load');
|
|
1626
1689
|
this.__data_frozen = true;
|
|
1627
1690
|
return;
|
|
1628
1691
|
}
|
|
@@ -1731,7 +1794,7 @@ class Jqhtml_Component {
|
|
|
1731
1794
|
// - Should errors reset state machine flags (next_reload_force_refresh)?
|
|
1732
1795
|
// - Should partial data be preserved or rolled back?
|
|
1733
1796
|
// - Should followers be notified differently based on error type?
|
|
1734
|
-
await this.on_load
|
|
1797
|
+
await this._call_lifecycle('on_load', restricted_this);
|
|
1735
1798
|
}
|
|
1736
1799
|
catch (error) {
|
|
1737
1800
|
// Handle error and notify coordinator
|
|
@@ -1803,7 +1866,7 @@ class Jqhtml_Component {
|
|
|
1803
1866
|
this._log_lifecycle('ready', 'start');
|
|
1804
1867
|
// Wait for all children to reach ready state (bottom-up execution)
|
|
1805
1868
|
await this._wait_for_children_ready();
|
|
1806
|
-
await this.on_ready
|
|
1869
|
+
await this._call_lifecycle('on_ready');
|
|
1807
1870
|
this._ready_state = 4;
|
|
1808
1871
|
this._update_debug_attrs();
|
|
1809
1872
|
this._log_lifecycle('ready', 'complete');
|
|
@@ -2019,7 +2082,7 @@ class Jqhtml_Component {
|
|
|
2019
2082
|
this.data = JSON.parse(JSON.stringify(this.__initial_data_snapshot));
|
|
2020
2083
|
}
|
|
2021
2084
|
try {
|
|
2022
|
-
await this.on_load
|
|
2085
|
+
await this._call_lifecycle('on_load');
|
|
2023
2086
|
}
|
|
2024
2087
|
finally {
|
|
2025
2088
|
// Freeze this.data after on_load() completes
|
|
@@ -2095,7 +2158,7 @@ class Jqhtml_Component {
|
|
|
2095
2158
|
// STEP 3.5 & 4: Wait for children and call on_ready (only if we rendered)
|
|
2096
2159
|
if (rendered_from_cache || should_render) {
|
|
2097
2160
|
await this._wait_for_children_ready();
|
|
2098
|
-
await this.on_ready
|
|
2161
|
+
await this._call_lifecycle('on_ready');
|
|
2099
2162
|
}
|
|
2100
2163
|
this._log_lifecycle('reload', 'complete');
|
|
2101
2164
|
}
|
|
@@ -2129,16 +2192,14 @@ class Jqhtml_Component {
|
|
|
2129
2192
|
this.$.addClass('_Component_Stopped');
|
|
2130
2193
|
// Unregister from lifecycle manager
|
|
2131
2194
|
this._lifecycle_manager.unregister_component(this);
|
|
2132
|
-
// Call user's on_stop() hook
|
|
2133
|
-
const stopResult = this.on_stop
|
|
2195
|
+
// Call user's on_stop() hook with authorization (sync)
|
|
2196
|
+
const stopResult = this._call_lifecycle_sync('on_stop');
|
|
2134
2197
|
if (stopResult && typeof stopResult.then === 'function') {
|
|
2135
2198
|
console.warn(`[JQHTML] Component "${this.component_name()}" returned a Promise from on_stop(). ` +
|
|
2136
2199
|
`on_stop() must be synchronous code. Remove 'async' from the function declaration.`);
|
|
2137
2200
|
}
|
|
2138
|
-
// Fire registered
|
|
2139
|
-
this.trigger('
|
|
2140
|
-
// Trigger jQuery destroy event
|
|
2141
|
-
this.$.trigger('destroy');
|
|
2201
|
+
// Fire registered stop callbacks
|
|
2202
|
+
this.trigger('stop');
|
|
2142
2203
|
// Remove from DOM parent's children
|
|
2143
2204
|
if (this._dom_parent) {
|
|
2144
2205
|
this._dom_parent._dom_children.delete(this);
|
|
@@ -3096,388 +3157,6 @@ function hydrateElement($element, jQ) {
|
|
|
3096
3157
|
}
|
|
3097
3158
|
}
|
|
3098
3159
|
|
|
3099
|
-
/**
|
|
3100
|
-
* JQHTML Debug Overlay
|
|
3101
|
-
*
|
|
3102
|
-
* Independent debug controls using pure jQuery DOM manipulation.
|
|
3103
|
-
* Does NOT use JQHTML components so it works even when components are broken.
|
|
3104
|
-
*/
|
|
3105
|
-
// Get global jQuery
|
|
3106
|
-
function getJQuery() {
|
|
3107
|
-
if (typeof window !== 'undefined' && window.$) {
|
|
3108
|
-
return window.$;
|
|
3109
|
-
}
|
|
3110
|
-
if (typeof window !== 'undefined' && window.jQuery) {
|
|
3111
|
-
return window.jQuery;
|
|
3112
|
-
}
|
|
3113
|
-
throw new Error('FATAL: jQuery is not defined. jQuery must be loaded before using JQHTML. ' +
|
|
3114
|
-
'Add <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> before loading JQHTML.');
|
|
3115
|
-
}
|
|
3116
|
-
// Get global jqhtml object
|
|
3117
|
-
function getJqhtml() {
|
|
3118
|
-
if (typeof window !== 'undefined' && window.jqhtml) {
|
|
3119
|
-
return window.jqhtml;
|
|
3120
|
-
}
|
|
3121
|
-
if (typeof globalThis !== 'undefined' && globalThis.jqhtml) {
|
|
3122
|
-
return globalThis.jqhtml;
|
|
3123
|
-
}
|
|
3124
|
-
throw new Error('FATAL: window.jqhtml is not defined. The JQHTML runtime must be loaded before using JQHTML components. ' +
|
|
3125
|
-
'Ensure @jqhtml/core is imported and initialized before attempting to use debug features.');
|
|
3126
|
-
}
|
|
3127
|
-
class DebugOverlay {
|
|
3128
|
-
constructor(options = {}) {
|
|
3129
|
-
this.$container = null;
|
|
3130
|
-
this.$statusIndicator = null;
|
|
3131
|
-
this.$ = getJQuery();
|
|
3132
|
-
if (!this.$) {
|
|
3133
|
-
throw new Error('jQuery is required for DebugOverlay');
|
|
3134
|
-
}
|
|
3135
|
-
this.options = {
|
|
3136
|
-
position: 'bottom',
|
|
3137
|
-
theme: 'dark',
|
|
3138
|
-
compact: false,
|
|
3139
|
-
showStatus: true,
|
|
3140
|
-
autoHide: false,
|
|
3141
|
-
...options
|
|
3142
|
-
};
|
|
3143
|
-
}
|
|
3144
|
-
/**
|
|
3145
|
-
* Static method to show debug overlay (singleton pattern)
|
|
3146
|
-
*/
|
|
3147
|
-
static show(options) {
|
|
3148
|
-
if (!DebugOverlay.instance) {
|
|
3149
|
-
DebugOverlay.instance = new DebugOverlay(options);
|
|
3150
|
-
}
|
|
3151
|
-
DebugOverlay.instance.display();
|
|
3152
|
-
return DebugOverlay.instance;
|
|
3153
|
-
}
|
|
3154
|
-
/**
|
|
3155
|
-
* Static method to hide debug overlay
|
|
3156
|
-
*/
|
|
3157
|
-
static hide() {
|
|
3158
|
-
if (DebugOverlay.instance) {
|
|
3159
|
-
DebugOverlay.instance.hide();
|
|
3160
|
-
}
|
|
3161
|
-
}
|
|
3162
|
-
/**
|
|
3163
|
-
* Static method to toggle debug overlay visibility
|
|
3164
|
-
*/
|
|
3165
|
-
static toggle() {
|
|
3166
|
-
if (DebugOverlay.instance && DebugOverlay.instance.$container) {
|
|
3167
|
-
if (DebugOverlay.instance.$container.is(':visible')) {
|
|
3168
|
-
DebugOverlay.hide();
|
|
3169
|
-
}
|
|
3170
|
-
else {
|
|
3171
|
-
DebugOverlay.instance.display();
|
|
3172
|
-
}
|
|
3173
|
-
}
|
|
3174
|
-
else {
|
|
3175
|
-
DebugOverlay.show();
|
|
3176
|
-
}
|
|
3177
|
-
}
|
|
3178
|
-
/**
|
|
3179
|
-
* Static method to destroy debug overlay
|
|
3180
|
-
*/
|
|
3181
|
-
static destroy() {
|
|
3182
|
-
if (DebugOverlay.instance) {
|
|
3183
|
-
DebugOverlay.instance.destroy();
|
|
3184
|
-
DebugOverlay.instance = null;
|
|
3185
|
-
}
|
|
3186
|
-
}
|
|
3187
|
-
/**
|
|
3188
|
-
* Display the debug overlay
|
|
3189
|
-
*/
|
|
3190
|
-
display() {
|
|
3191
|
-
if (this.$container) {
|
|
3192
|
-
this.$container.show();
|
|
3193
|
-
return;
|
|
3194
|
-
}
|
|
3195
|
-
this.createOverlay();
|
|
3196
|
-
if (this.options.showStatus) {
|
|
3197
|
-
this.createStatusIndicator();
|
|
3198
|
-
}
|
|
3199
|
-
}
|
|
3200
|
-
/**
|
|
3201
|
-
* Hide the debug overlay
|
|
3202
|
-
*/
|
|
3203
|
-
hide() {
|
|
3204
|
-
if (this.$container) {
|
|
3205
|
-
this.$container.hide();
|
|
3206
|
-
}
|
|
3207
|
-
if (this.$statusIndicator) {
|
|
3208
|
-
this.$statusIndicator.hide();
|
|
3209
|
-
}
|
|
3210
|
-
}
|
|
3211
|
-
/**
|
|
3212
|
-
* Remove the debug overlay completely
|
|
3213
|
-
*/
|
|
3214
|
-
destroy() {
|
|
3215
|
-
if (this.$container) {
|
|
3216
|
-
this.$container.remove();
|
|
3217
|
-
this.$container = null;
|
|
3218
|
-
}
|
|
3219
|
-
if (this.$statusIndicator) {
|
|
3220
|
-
this.$statusIndicator.remove();
|
|
3221
|
-
this.$statusIndicator = null;
|
|
3222
|
-
}
|
|
3223
|
-
}
|
|
3224
|
-
/**
|
|
3225
|
-
* Update the status indicator
|
|
3226
|
-
*/
|
|
3227
|
-
updateStatus(mode) {
|
|
3228
|
-
if (!this.$statusIndicator)
|
|
3229
|
-
return;
|
|
3230
|
-
this.$statusIndicator.text('Debug: ' + mode);
|
|
3231
|
-
this.$statusIndicator.attr('class', 'jqhtml-debug-status' + (mode !== 'Off' ? ' active' : ''));
|
|
3232
|
-
}
|
|
3233
|
-
createOverlay() {
|
|
3234
|
-
// Add styles first
|
|
3235
|
-
this.addStyles();
|
|
3236
|
-
// Create container using jQuery
|
|
3237
|
-
this.$container = this.$('<div>')
|
|
3238
|
-
.addClass(`jqhtml-debug-overlay ${this.options.theme} ${this.options.position}`);
|
|
3239
|
-
// Create content structure
|
|
3240
|
-
const $content = this.$('<div>').addClass('jqhtml-debug-content');
|
|
3241
|
-
const $controls = this.$('<div>').addClass('jqhtml-debug-controls');
|
|
3242
|
-
// Add title
|
|
3243
|
-
const $title = this.$('<span>')
|
|
3244
|
-
.addClass('jqhtml-debug-title')
|
|
3245
|
-
.html('<strong>🐛 JQHTML Debug:</strong>');
|
|
3246
|
-
$controls.append($title);
|
|
3247
|
-
// Create buttons
|
|
3248
|
-
const buttons = [
|
|
3249
|
-
{ text: 'Slow Motion + Flash', action: 'enableSlowMotionDebug', class: 'success' },
|
|
3250
|
-
{ text: 'Basic Debug', action: 'enableBasicDebug', class: '' },
|
|
3251
|
-
{ text: 'Full Debug', action: 'enableFullDebug', class: '' },
|
|
3252
|
-
{ text: 'Sequential', action: 'enableSequentialMode', class: '' },
|
|
3253
|
-
{ text: 'Clear Debug', action: 'clearAllDebug', class: 'danger' },
|
|
3254
|
-
{ text: 'Settings', action: 'showDebugInfo', class: '' }
|
|
3255
|
-
];
|
|
3256
|
-
buttons.forEach(btn => {
|
|
3257
|
-
const $button = this.$('<button>')
|
|
3258
|
-
.text(btn.text)
|
|
3259
|
-
.addClass('jqhtml-debug-btn' + (btn.class ? ` ${btn.class}` : ''))
|
|
3260
|
-
.on('click', () => this.executeAction(btn.action));
|
|
3261
|
-
$controls.append($button);
|
|
3262
|
-
});
|
|
3263
|
-
// Add minimize/close button
|
|
3264
|
-
const $toggleBtn = this.$('<button>')
|
|
3265
|
-
.text(this.options.compact ? '▼' : '▲')
|
|
3266
|
-
.addClass('jqhtml-debug-toggle')
|
|
3267
|
-
.on('click', () => this.toggle());
|
|
3268
|
-
$controls.append($toggleBtn);
|
|
3269
|
-
// Assemble and add to page
|
|
3270
|
-
$content.append($controls);
|
|
3271
|
-
this.$container.append($content);
|
|
3272
|
-
this.$('body').append(this.$container);
|
|
3273
|
-
}
|
|
3274
|
-
createStatusIndicator() {
|
|
3275
|
-
this.$statusIndicator = this.$('<div>')
|
|
3276
|
-
.addClass('jqhtml-debug-status')
|
|
3277
|
-
.text('Debug: Off')
|
|
3278
|
-
.css({
|
|
3279
|
-
position: 'fixed',
|
|
3280
|
-
top: '10px',
|
|
3281
|
-
right: '10px',
|
|
3282
|
-
background: '#2c3e50',
|
|
3283
|
-
color: 'white',
|
|
3284
|
-
padding: '5px 10px',
|
|
3285
|
-
borderRadius: '4px',
|
|
3286
|
-
fontSize: '0.75rem',
|
|
3287
|
-
zIndex: '10001',
|
|
3288
|
-
opacity: '0.8',
|
|
3289
|
-
fontFamily: 'monospace'
|
|
3290
|
-
});
|
|
3291
|
-
this.$('body').append(this.$statusIndicator);
|
|
3292
|
-
}
|
|
3293
|
-
addStyles() {
|
|
3294
|
-
// Check if styles already exist
|
|
3295
|
-
if (this.$('#jqhtml-debug-styles').length > 0)
|
|
3296
|
-
return;
|
|
3297
|
-
// Create and inject CSS using jQuery - concatenated strings for better minification
|
|
3298
|
-
const $style = this.$('<style>')
|
|
3299
|
-
.attr('id', 'jqhtml-debug-styles')
|
|
3300
|
-
.text('.jqhtml-debug-overlay {' +
|
|
3301
|
-
'position: fixed;' +
|
|
3302
|
-
'left: 0;' +
|
|
3303
|
-
'right: 0;' +
|
|
3304
|
-
'z-index: 10000;' +
|
|
3305
|
-
'font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, monospace;' +
|
|
3306
|
-
'font-size: 0.8rem;' +
|
|
3307
|
-
'box-shadow: 0 2px 10px rgba(0,0,0,0.2);' +
|
|
3308
|
-
'}' +
|
|
3309
|
-
'.jqhtml-debug-overlay.top {' +
|
|
3310
|
-
'top: 0;' +
|
|
3311
|
-
'}' +
|
|
3312
|
-
'.jqhtml-debug-overlay.bottom {' +
|
|
3313
|
-
'bottom: 0;' +
|
|
3314
|
-
'}' +
|
|
3315
|
-
'.jqhtml-debug-overlay.dark {' +
|
|
3316
|
-
'background: #34495e;' +
|
|
3317
|
-
'color: #ecf0f1;' +
|
|
3318
|
-
'}' +
|
|
3319
|
-
'.jqhtml-debug-overlay.light {' +
|
|
3320
|
-
'background: #f8f9fa;' +
|
|
3321
|
-
'color: #333;' +
|
|
3322
|
-
'border-bottom: 1px solid #dee2e6;' +
|
|
3323
|
-
'}' +
|
|
3324
|
-
'.jqhtml-debug-content {' +
|
|
3325
|
-
'padding: 0.5rem 1rem;' +
|
|
3326
|
-
'}' +
|
|
3327
|
-
'.jqhtml-debug-controls {' +
|
|
3328
|
-
'display: flex;' +
|
|
3329
|
-
'flex-wrap: wrap;' +
|
|
3330
|
-
'gap: 8px;' +
|
|
3331
|
-
'align-items: center;' +
|
|
3332
|
-
'}' +
|
|
3333
|
-
'.jqhtml-debug-title {' +
|
|
3334
|
-
'margin-right: 10px;' +
|
|
3335
|
-
'font-weight: bold;' +
|
|
3336
|
-
'}' +
|
|
3337
|
-
'.jqhtml-debug-btn {' +
|
|
3338
|
-
'padding: 4px 8px;' +
|
|
3339
|
-
'border: none;' +
|
|
3340
|
-
'border-radius: 3px;' +
|
|
3341
|
-
'background: #3498db;' +
|
|
3342
|
-
'color: white;' +
|
|
3343
|
-
'cursor: pointer;' +
|
|
3344
|
-
'font-size: 0.75rem;' +
|
|
3345
|
-
'transition: background 0.2s;' +
|
|
3346
|
-
'}' +
|
|
3347
|
-
'.jqhtml-debug-btn:hover {' +
|
|
3348
|
-
'background: #2980b9;' +
|
|
3349
|
-
'}' +
|
|
3350
|
-
'.jqhtml-debug-btn.success {' +
|
|
3351
|
-
'background: #27ae60;' +
|
|
3352
|
-
'}' +
|
|
3353
|
-
'.jqhtml-debug-btn.success:hover {' +
|
|
3354
|
-
'background: #229954;' +
|
|
3355
|
-
'}' +
|
|
3356
|
-
'.jqhtml-debug-btn.danger {' +
|
|
3357
|
-
'background: #e74c3c;' +
|
|
3358
|
-
'}' +
|
|
3359
|
-
'.jqhtml-debug-btn.danger:hover {' +
|
|
3360
|
-
'background: #c0392b;' +
|
|
3361
|
-
'}' +
|
|
3362
|
-
'.jqhtml-debug-toggle {' +
|
|
3363
|
-
'padding: 4px 8px;' +
|
|
3364
|
-
'border: none;' +
|
|
3365
|
-
'border-radius: 3px;' +
|
|
3366
|
-
'background: #7f8c8d;' +
|
|
3367
|
-
'color: white;' +
|
|
3368
|
-
'cursor: pointer;' +
|
|
3369
|
-
'font-size: 0.75rem;' +
|
|
3370
|
-
'margin-left: auto;' +
|
|
3371
|
-
'}' +
|
|
3372
|
-
'.jqhtml-debug-toggle:hover {' +
|
|
3373
|
-
'background: #6c7b7d;' +
|
|
3374
|
-
'}' +
|
|
3375
|
-
'.jqhtml-debug-status.active {' +
|
|
3376
|
-
'background: #27ae60 !important;' +
|
|
3377
|
-
'}' +
|
|
3378
|
-
'@media (max-width: 768px) {' +
|
|
3379
|
-
'.jqhtml-debug-controls {' +
|
|
3380
|
-
'flex-direction: column;' +
|
|
3381
|
-
'align-items: flex-start;' +
|
|
3382
|
-
'}' +
|
|
3383
|
-
'.jqhtml-debug-title {' +
|
|
3384
|
-
'margin-bottom: 5px;' +
|
|
3385
|
-
'}' +
|
|
3386
|
-
'}');
|
|
3387
|
-
this.$('head').append($style);
|
|
3388
|
-
}
|
|
3389
|
-
toggle() {
|
|
3390
|
-
// Toggle between compact and full view
|
|
3391
|
-
this.options.compact = !this.options.compact;
|
|
3392
|
-
const $toggleBtn = this.$container.find('.jqhtml-debug-toggle');
|
|
3393
|
-
$toggleBtn.text(this.options.compact ? '▼' : '▲');
|
|
3394
|
-
const $buttons = this.$container.find('.jqhtml-debug-btn');
|
|
3395
|
-
if (this.options.compact) {
|
|
3396
|
-
$buttons.hide();
|
|
3397
|
-
}
|
|
3398
|
-
else {
|
|
3399
|
-
$buttons.show();
|
|
3400
|
-
}
|
|
3401
|
-
}
|
|
3402
|
-
executeAction(action) {
|
|
3403
|
-
const jqhtml = getJqhtml();
|
|
3404
|
-
if (!jqhtml) {
|
|
3405
|
-
console.warn('JQHTML not available - make sure it\'s loaded and exposed globally');
|
|
3406
|
-
return;
|
|
3407
|
-
}
|
|
3408
|
-
switch (action) {
|
|
3409
|
-
case 'enableSlowMotionDebug':
|
|
3410
|
-
jqhtml.setDebugSettings({
|
|
3411
|
-
logFullLifecycle: true,
|
|
3412
|
-
sequentialProcessing: true,
|
|
3413
|
-
delayAfterComponent: 150,
|
|
3414
|
-
delayAfterRender: 200,
|
|
3415
|
-
delayAfterRerender: 250,
|
|
3416
|
-
flashComponents: true,
|
|
3417
|
-
flashDuration: 800,
|
|
3418
|
-
flashColors: {
|
|
3419
|
-
create: '#3498db',
|
|
3420
|
-
render: '#27ae60',
|
|
3421
|
-
ready: '#9b59b6'
|
|
3422
|
-
},
|
|
3423
|
-
profilePerformance: true,
|
|
3424
|
-
highlightSlowRenders: 30,
|
|
3425
|
-
logDispatch: true
|
|
3426
|
-
});
|
|
3427
|
-
this.updateStatus('Slow Motion');
|
|
3428
|
-
console.log('🐛 Slow Motion Debug Mode Enabled');
|
|
3429
|
-
break;
|
|
3430
|
-
case 'enableBasicDebug':
|
|
3431
|
-
jqhtml.enableDebugMode('basic');
|
|
3432
|
-
this.updateStatus('Basic');
|
|
3433
|
-
console.log('🐛 Basic Debug Mode Enabled');
|
|
3434
|
-
break;
|
|
3435
|
-
case 'enableFullDebug':
|
|
3436
|
-
jqhtml.enableDebugMode('full');
|
|
3437
|
-
this.updateStatus('Full');
|
|
3438
|
-
console.log('🐛 Full Debug Mode Enabled');
|
|
3439
|
-
break;
|
|
3440
|
-
case 'enableSequentialMode':
|
|
3441
|
-
jqhtml.setDebugSettings({
|
|
3442
|
-
logCreationReady: true,
|
|
3443
|
-
sequentialProcessing: true,
|
|
3444
|
-
flashComponents: true,
|
|
3445
|
-
profilePerformance: true
|
|
3446
|
-
});
|
|
3447
|
-
this.updateStatus('Sequential');
|
|
3448
|
-
console.log('🐛 Sequential Processing Mode Enabled');
|
|
3449
|
-
break;
|
|
3450
|
-
case 'clearAllDebug':
|
|
3451
|
-
jqhtml.clearDebugSettings();
|
|
3452
|
-
this.updateStatus('Off');
|
|
3453
|
-
console.log('🐛 All Debug Modes Disabled');
|
|
3454
|
-
break;
|
|
3455
|
-
case 'showDebugInfo':
|
|
3456
|
-
const settings = JSON.stringify(jqhtml.debug, null, 2);
|
|
3457
|
-
console.log('🐛 Current Debug Settings:', settings);
|
|
3458
|
-
alert('Debug settings logged to console:\n\n' + (Object.keys(jqhtml.debug).length > 0 ? settings : 'No debug settings active'));
|
|
3459
|
-
break;
|
|
3460
|
-
}
|
|
3461
|
-
}
|
|
3462
|
-
}
|
|
3463
|
-
DebugOverlay.instance = null;
|
|
3464
|
-
// Simplified global convenience functions that use static methods
|
|
3465
|
-
function showDebugOverlay(options) {
|
|
3466
|
-
return DebugOverlay.show(options);
|
|
3467
|
-
}
|
|
3468
|
-
function hideDebugOverlay() {
|
|
3469
|
-
DebugOverlay.hide();
|
|
3470
|
-
}
|
|
3471
|
-
// Auto-initialize if debug query parameter is present
|
|
3472
|
-
if (typeof window !== 'undefined') {
|
|
3473
|
-
const urlParams = new URLSearchParams(window.location.search);
|
|
3474
|
-
if (urlParams.get('debug') === 'true' || urlParams.get('jqhtml-debug') === 'true') {
|
|
3475
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
3476
|
-
DebugOverlay.show();
|
|
3477
|
-
});
|
|
3478
|
-
}
|
|
3479
|
-
}
|
|
3480
|
-
|
|
3481
3160
|
/**
|
|
3482
3161
|
* JQHTML v2 jQuery Plugin
|
|
3483
3162
|
*
|
|
@@ -4376,7 +4055,7 @@ function init(jQuery) {
|
|
|
4376
4055
|
}
|
|
4377
4056
|
}
|
|
4378
4057
|
// Version - will be replaced during build with actual version from package.json
|
|
4379
|
-
const version = '2.3.
|
|
4058
|
+
const version = '2.3.6';
|
|
4380
4059
|
// Default export with all functionality
|
|
4381
4060
|
const jqhtml = {
|
|
4382
4061
|
// Core
|
|
@@ -4400,6 +4079,8 @@ const jqhtml = {
|
|
|
4400
4079
|
escape_html,
|
|
4401
4080
|
// Version property - internal
|
|
4402
4081
|
__version: version,
|
|
4082
|
+
// state facts
|
|
4083
|
+
tombstone: 'pepperoni and cheese',
|
|
4403
4084
|
// Debug settings
|
|
4404
4085
|
debug: {
|
|
4405
4086
|
enabled: false,
|
|
@@ -4426,15 +4107,6 @@ const jqhtml = {
|
|
|
4426
4107
|
clearDebugSettings() {
|
|
4427
4108
|
this.debug = {};
|
|
4428
4109
|
},
|
|
4429
|
-
// Debug overlay methods
|
|
4430
|
-
showDebugOverlay(options) {
|
|
4431
|
-
return DebugOverlay.show(options);
|
|
4432
|
-
},
|
|
4433
|
-
hideDebugOverlay() {
|
|
4434
|
-
return DebugOverlay.hide();
|
|
4435
|
-
},
|
|
4436
|
-
// Export DebugOverlay class for direct access
|
|
4437
|
-
DebugOverlay,
|
|
4438
4110
|
// Install globals function
|
|
4439
4111
|
installGlobals() {
|
|
4440
4112
|
if (typeof window !== 'undefined') {
|
|
@@ -4488,5 +4160,5 @@ if (typeof window !== 'undefined' && !window.jqhtml) {
|
|
|
4488
4160
|
}
|
|
4489
4161
|
}
|
|
4490
4162
|
|
|
4491
|
-
export {
|
|
4163
|
+
export { Jqhtml_Component, LifecycleManager as Jqhtml_LifecycleManager, Jqhtml_Local_Storage, LifecycleManager, Load_Coordinator, applyDebugDelay, boot, create_component, jqhtml as default, devWarn, escape_html, extract_slots, get_component_class, get_component_names, get_registered_templates, get_template, get_template_by_class, handleComponentError, has_component, init, init_jquery_plugin, isSequentialProcessing, list_components, logDataChange, logDispatch, logInstruction, logLifecycle, process_instructions, register_component, register_template, render_template, version };
|
|
4492
4164
|
//# sourceMappingURL=jqhtml-core.esm.js.map
|