diff --git a/capabilities/testdrive-jsui/js/controls/contents-control.js b/capabilities/testdrive-jsui/js/controls/contents-control.js index c5bdcdca..680dbc33 100644 --- a/capabilities/testdrive-jsui/js/controls/contents-control.js +++ b/capabilities/testdrive-jsui/js/controls/contents-control.js @@ -10,7 +10,6 @@ * - Hierarchical display with proper indentation * - Clickable navigation links with smooth scrolling * - Real-time updates when document structure changes - * - Collapsible sections for better organization * - Search functionality within the table of contents * * Dependencies: @@ -20,9 +19,9 @@ /** * ContentsControl - Interactive table of contents control * - * This control scans the document for headings (h1-h6) and presents them - * in a navigable tree structure. Users can click on any heading to jump - * directly to that section with smooth scrolling. + * Built on the base class architecture for consistency with other panels. + * Only implements content-specific functionality while inheriting all + * common panel behavior from ControlBase. */ class ContentsControl extends ControlBase { constructor() { @@ -45,6 +44,80 @@ class ContentsControl extends ControlBase { this.searchQuery = ''; } + /** + * Generate contents control content (called by base class buildContent) + */ + generateContent() { + // Extract headings first + this.extractHeadings(); + + return this.safeOperation(() => { + if (this.headings.length === 0) { + return ` +
No headings found in document
+ +No headings found in document
- -Error generating contents
', 'generateContentsHTML'); - } - /** * Navigate to a specific heading with smooth scrolling */ @@ -212,20 +217,7 @@ class ContentsControl extends ControlBase { */ handleSearch(query) { this.searchQuery = query; - const filteredHeadings = this.filterHeadings(this.headings, query); - this.updateContentsDisplay(filteredHeadings); - } - - /** - * Update the contents display with new headings - */ - updateContentsDisplay(headings) { - return this.safeOperation(() => { - const content = this.element?.querySelector('.control-content'); - if (content) { - content.innerHTML = this.generateContentsHTML(headings); - } - }, null, 'updateContentsDisplay'); + this.buildContent(); // Rebuild content with new filter } /** @@ -234,12 +226,11 @@ class ContentsControl extends ControlBase { refreshContents() { return this.safeOperation(() => { this.extractHeadings(); - const filteredHeadings = this.filterHeadings(this.headings, this.searchQuery); - this.updateContentsDisplay(filteredHeadings); + this.buildContent(); // Rebuild content with updated headings // Show success feedback const refreshBtn = this.element?.querySelector('button'); - if (refreshBtn) { + if (refreshBtn && refreshBtn.textContent.includes('Refresh')) { const originalText = refreshBtn.innerHTML; refreshBtn.innerHTML = '✅ Updated'; refreshBtn.style.background = '#28a745'; @@ -252,23 +243,6 @@ class ContentsControl extends ControlBase { }, null, 'refreshContents'); } - /** - * Build the control content - * Override of base class method to provide contents-specific functionality - */ - - /** - * Generate contents control content (called by base class buildContent) - */ - generateContent() { - // Extract headings first - this.extractHeadings(); - - return this.safeOperation(() => { - return this.generateContentsHTML(); - }, 'Error generating contents', 'generateContent'); - } - /** * Override buildContent to add control reference and auto-refresh */ @@ -293,37 +267,6 @@ class ContentsControl extends ControlBase { }, 5000); // Check every 5 seconds } - /** - * Get statistics about the document structure - */ - getDocumentStats() { - return this.safeOperation(() => { - const stats = { - totalHeadings: this.headings.length, - byLevel: {}, - deepestLevel: 1, - structure: 'flat' - }; - - // Count headings by level - this.headings.forEach(heading => { - stats.byLevel[heading.level] = (stats.byLevel[heading.level] || 0) + 1; - stats.deepestLevel = Math.max(stats.deepestLevel, heading.level); - }); - - // Determine structure type - const levels = Object.keys(stats.byLevel).map(Number).sort(); - if (levels.length > 1) { - const hasSequentialLevels = levels.every((level, index) => - index === 0 || level <= levels[index - 1] + 1 - ); - stats.structure = hasSequentialLevels ? 'hierarchical' : 'mixed'; - } - - return stats; - }, {}, 'getDocumentStats'); - } - /** * Clean up resources when control is destroyed */ diff --git a/capabilities/testdrive-jsui/js/controls/control-base.js b/capabilities/testdrive-jsui/js/controls/control-base.js index 98789fa6..35a94d38 100644 --- a/capabilities/testdrive-jsui/js/controls/control-base.js +++ b/capabilities/testdrive-jsui/js/controls/control-base.js @@ -541,7 +541,7 @@ class ControlBase { resizeHandle.style.cssText = ` position: absolute; bottom: 0px; - right: -4px; + right: 1px; width: 12px; height: 12px; cursor: se-resize; diff --git a/testdrive-jsui/static/js/controls/contents-control.js b/testdrive-jsui/static/js/controls/contents-control.js index c5bdcdca..680dbc33 100644 --- a/testdrive-jsui/static/js/controls/contents-control.js +++ b/testdrive-jsui/static/js/controls/contents-control.js @@ -10,7 +10,6 @@ * - Hierarchical display with proper indentation * - Clickable navigation links with smooth scrolling * - Real-time updates when document structure changes - * - Collapsible sections for better organization * - Search functionality within the table of contents * * Dependencies: @@ -20,9 +19,9 @@ /** * ContentsControl - Interactive table of contents control * - * This control scans the document for headings (h1-h6) and presents them - * in a navigable tree structure. Users can click on any heading to jump - * directly to that section with smooth scrolling. + * Built on the base class architecture for consistency with other panels. + * Only implements content-specific functionality while inheriting all + * common panel behavior from ControlBase. */ class ContentsControl extends ControlBase { constructor() { @@ -45,6 +44,80 @@ class ContentsControl extends ControlBase { this.searchQuery = ''; } + /** + * Generate contents control content (called by base class buildContent) + */ + generateContent() { + // Extract headings first + this.extractHeadings(); + + return this.safeOperation(() => { + if (this.headings.length === 0) { + return ` +No headings found in document
+ +No headings found in document
- -Error generating contents
', 'generateContentsHTML'); - } - /** * Navigate to a specific heading with smooth scrolling */ @@ -212,20 +217,7 @@ class ContentsControl extends ControlBase { */ handleSearch(query) { this.searchQuery = query; - const filteredHeadings = this.filterHeadings(this.headings, query); - this.updateContentsDisplay(filteredHeadings); - } - - /** - * Update the contents display with new headings - */ - updateContentsDisplay(headings) { - return this.safeOperation(() => { - const content = this.element?.querySelector('.control-content'); - if (content) { - content.innerHTML = this.generateContentsHTML(headings); - } - }, null, 'updateContentsDisplay'); + this.buildContent(); // Rebuild content with new filter } /** @@ -234,12 +226,11 @@ class ContentsControl extends ControlBase { refreshContents() { return this.safeOperation(() => { this.extractHeadings(); - const filteredHeadings = this.filterHeadings(this.headings, this.searchQuery); - this.updateContentsDisplay(filteredHeadings); + this.buildContent(); // Rebuild content with updated headings // Show success feedback const refreshBtn = this.element?.querySelector('button'); - if (refreshBtn) { + if (refreshBtn && refreshBtn.textContent.includes('Refresh')) { const originalText = refreshBtn.innerHTML; refreshBtn.innerHTML = '✅ Updated'; refreshBtn.style.background = '#28a745'; @@ -252,23 +243,6 @@ class ContentsControl extends ControlBase { }, null, 'refreshContents'); } - /** - * Build the control content - * Override of base class method to provide contents-specific functionality - */ - - /** - * Generate contents control content (called by base class buildContent) - */ - generateContent() { - // Extract headings first - this.extractHeadings(); - - return this.safeOperation(() => { - return this.generateContentsHTML(); - }, 'Error generating contents', 'generateContent'); - } - /** * Override buildContent to add control reference and auto-refresh */ @@ -293,37 +267,6 @@ class ContentsControl extends ControlBase { }, 5000); // Check every 5 seconds } - /** - * Get statistics about the document structure - */ - getDocumentStats() { - return this.safeOperation(() => { - const stats = { - totalHeadings: this.headings.length, - byLevel: {}, - deepestLevel: 1, - structure: 'flat' - }; - - // Count headings by level - this.headings.forEach(heading => { - stats.byLevel[heading.level] = (stats.byLevel[heading.level] || 0) + 1; - stats.deepestLevel = Math.max(stats.deepestLevel, heading.level); - }); - - // Determine structure type - const levels = Object.keys(stats.byLevel).map(Number).sort(); - if (levels.length > 1) { - const hasSequentialLevels = levels.every((level, index) => - index === 0 || level <= levels[index - 1] + 1 - ); - stats.structure = hasSequentialLevels ? 'hierarchical' : 'mixed'; - } - - return stats; - }, {}, 'getDocumentStats'); - } - /** * Clean up resources when control is destroyed */ diff --git a/testdrive-jsui/static/js/controls/control-base.js b/testdrive-jsui/static/js/controls/control-base.js index 98789fa6..ecb826e0 100644 --- a/testdrive-jsui/static/js/controls/control-base.js +++ b/testdrive-jsui/static/js/controls/control-base.js @@ -541,7 +541,7 @@ class ControlBase { resizeHandle.style.cssText = ` position: absolute; bottom: 0px; - right: -4px; + right: 2px; width: 12px; height: 12px; cursor: se-resize;