213 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			213 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
 | 
						|
// Base filesystem class that defines the common interface for all filesystem implementations.
 | 
						|
// Now supports multi-value result rows (bytes, sectors, etc.) in a single output line.
 | 
						|
 | 
						|
import { parseHex, validateInput, checkDependencies, updateResultItem } from '../utils.js';
 | 
						|
 | 
						|
export class BaseFilesystem {
 | 
						|
    constructor(name, variants = []) {
 | 
						|
        this.name = name;
 | 
						|
        this.variants = variants; // Array of variant configurations
 | 
						|
    }
 | 
						|
 | 
						|
    // Abstract method to be implemented by subclasses
 | 
						|
    getVariants() {
 | 
						|
        return this.variants;
 | 
						|
    }
 | 
						|
 | 
						|
    // Generate HTML for constants section
 | 
						|
    generateConstantsHTML(variantId) {
 | 
						|
        const variant = this.variants.find(v => v.id === variantId);
 | 
						|
        if (!variant) return '';
 | 
						|
 | 
						|
        // Helper function to format labels with offset information
 | 
						|
        const formatLabel = (label) => {
 | 
						|
            // Match patterns like "(Boot-Offset 0x00)", "(MFT-Header-Offset 0x14)", "(Offset 0x00)" and wrap offset info
 | 
						|
            const offsetPattern = /(\((Boot-Offset|MFT-Header-Offset|Offset) [^)]+\))/g;
 | 
						|
            return label.replace(offsetPattern, '<span class="offset-info">$1</span>');
 | 
						|
        };
 | 
						|
 | 
						|
        return `
 | 
						|
            <div class="section constants">
 | 
						|
                <h2>Konstanten</h2>
 | 
						|
                <div class="input-grid">
 | 
						|
                    ${variant.constants.map(constant => `
 | 
						|
                        <div class="input-group">
 | 
						|
                            <label for="${constant.id}">${formatLabel(constant.label)} <span class="unit-indicator">(${constant.unit})</span>:</label>
 | 
						|
                            <input type="text" id="${constant.id}" value="${constant.default}" placeholder="${constant.default}">
 | 
						|
                            <div class="error-message" id="${constant.id}-error"></div>
 | 
						|
                        </div>
 | 
						|
                    `).join('')}
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
        `;
 | 
						|
    }
 | 
						|
 | 
						|
    // Generate HTML for timestamp converter section (to be overridden by subclasses)
 | 
						|
    generateTimestampConverterHTML(variantId) {
 | 
						|
        // Default implementation returns empty string
 | 
						|
        // Subclasses can override to provide filesystem-specific converters
 | 
						|
        return '';
 | 
						|
    }
 | 
						|
 | 
						|
    // Generate HTML for input parameters section
 | 
						|
    generateInputsHTML(variantId) {
 | 
						|
        const variant = this.variants.find(v => v.id === variantId);
 | 
						|
        if (!variant) return '';
 | 
						|
 | 
						|
        // Helper function to format labels with offset information
 | 
						|
        const formatLabel = (label) => {
 | 
						|
            // Match patterns like "(Boot-Offset 0x00)", "(MFT-Header-Offset 0x14)", "(Offset 0x00)" and wrap offset info
 | 
						|
            const offsetPattern = /(\((Boot-Offset|MFT-Header-Offset|Offset) [^)]+\))/g;
 | 
						|
            return label.replace(offsetPattern, '<span class="offset-info">$1</span>');
 | 
						|
        };
 | 
						|
 | 
						|
        return `
 | 
						|
            <div class="section">
 | 
						|
                <h2>Eingabeparameter</h2>
 | 
						|
                <div class="input-grid">
 | 
						|
                    ${variant.inputs.map(input => `
 | 
						|
                        <div class="input-group">
 | 
						|
                            <label for="${input.id}">${formatLabel(input.label)} <span class="unit-indicator">(${input.unit})</span>:</label>
 | 
						|
                            <input type="text" id="${input.id}" placeholder="${input.placeholder}">
 | 
						|
                            <div class="error-message" id="${input.id}-error"></div>
 | 
						|
                        </div>
 | 
						|
                    `).join('')}
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
        `;
 | 
						|
    }
 | 
						|
 | 
						|
    // Generate HTML for results section
 | 
						|
    generateResultsHTML(variantId) {
 | 
						|
        const variant = this.variants.find(v => v.id === variantId);
 | 
						|
        if (!variant) return '';
 | 
						|
 | 
						|
        // Helper: get display units for a result (bytes, sectors, ...)
 | 
						|
        function getDisplayUnits(result) {
 | 
						|
            // Heuristic: if label contains (Bytes) or (Sektor), show both
 | 
						|
            const label = result.label.toLowerCase();
 | 
						|
            const units = [];
 | 
						|
            if (label.includes('bytes') || label.includes('byte')) units.push('bytes');
 | 
						|
            if (label.includes('sektor')) units.push('sectors');
 | 
						|
            // Add more as needed
 | 
						|
            return units;
 | 
						|
        }
 | 
						|
 | 
						|
        return `
 | 
						|
            <div class="section results">
 | 
						|
                <h2>Berechnete Werte</h2>
 | 
						|
                ${variant.resultGroups.map(group => `
 | 
						|
                    <div class="result-group">
 | 
						|
                        <h3>${group.name}</h3>
 | 
						|
                        ${group.results.map(result => {
 | 
						|
                            // For each result, show all representations in one row
 | 
						|
                            // The calculation logic must fill in all values in the result-value element, separated by //
 | 
						|
                            return `
 | 
						|
                                <div class="result-item" data-deps="${result.dependencies.join(',')}">
 | 
						|
                                    <span class="result-label" data-formula="${result.formula}">${result.label}:</span>
 | 
						|
                                    <div class="result-value-container">
 | 
						|
                                        <span class="result-value" id="${result.id}">-</span>
 | 
						|
                                        <button class="copy-btn" onclick="copyToClipboard('${result.id}')">📋</button>
 | 
						|
                                    </div>
 | 
						|
                                </div>
 | 
						|
                            `;
 | 
						|
                        }).join('')}
 | 
						|
                    </div>
 | 
						|
                `).join('')}
 | 
						|
            </div>
 | 
						|
        `;
 | 
						|
    }
 | 
						|
 | 
						|
    // Generate HTML for formulas section
 | 
						|
    generateFormulasHTML(variantId) {
 | 
						|
        const variant = this.variants.find(v => v.id === variantId);
 | 
						|
        if (!variant) return '';
 | 
						|
 | 
						|
        return `
 | 
						|
            <div class="section formulas">
 | 
						|
                <h2>Berechnungsformeln ${this.name}</h2>
 | 
						|
                <div class="formula-box">
 | 
						|
                    ${variant.formulas.map(formula => `
 | 
						|
                        <div class="formula"><span class="calculated">${formula.name}</span> = ${formula.expression}</div>
 | 
						|
                    `).join('')}
 | 
						|
                </div>
 | 
						|
            </div>
 | 
						|
        `;
 | 
						|
    }
 | 
						|
 | 
						|
    // Generate complete tab content HTML
 | 
						|
    generateTabContentHTML(variantId, calculatorHTML) {
 | 
						|
        const timestampHTML = this.generateTimestampConverterHTML(variantId);
 | 
						|
        
 | 
						|
        return `
 | 
						|
            <div class="tab-content" id="${variantId}">
 | 
						|
                <div class="constants-calculator-container">
 | 
						|
                    <div class="constants-tools-wrapper">
 | 
						|
                        ${this.generateConstantsHTML(variantId)}
 | 
						|
                        ${timestampHTML}
 | 
						|
                    </div>
 | 
						|
                    <div class="section hex-calculator">
 | 
						|
                        <h2>Hex-Rechner</h2>
 | 
						|
                        ${calculatorHTML}
 | 
						|
                    </div>
 | 
						|
                </div>
 | 
						|
                ${this.generateInputsHTML(variantId)}
 | 
						|
                ${this.generateResultsHTML(variantId)}
 | 
						|
                ${this.generateFormulasHTML(variantId)}
 | 
						|
            </div>
 | 
						|
        `;
 | 
						|
    }
 | 
						|
 | 
						|
    // Abstract method for calculations - to be implemented by subclasses
 | 
						|
    calculate(variantId) {
 | 
						|
        throw new Error('calculate method must be implemented by subclass');
 | 
						|
    }
 | 
						|
 | 
						|
    // Setup input event listeners for this filesystem
 | 
						|
    setupInputListeners(variantId) {
 | 
						|
        const variant = this.variants.find(v => v.id === variantId);
 | 
						|
        if (!variant) return;
 | 
						|
 | 
						|
        const allInputIds = [
 | 
						|
            ...variant.constants.map(c => c.id),
 | 
						|
            ...variant.inputs.map(i => i.id)
 | 
						|
        ];
 | 
						|
 | 
						|
        allInputIds.forEach(inputId => {
 | 
						|
            const input = document.getElementById(inputId);
 | 
						|
            if (input) {
 | 
						|
                input.addEventListener('input', () => {
 | 
						|
                    validateInput(inputId, input.value);
 | 
						|
                    this.calculate(variantId);
 | 
						|
                });
 | 
						|
            }
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    // Get all input values for a variant
 | 
						|
    getInputValues(variantId) {
 | 
						|
        const variant = this.variants.find(v => v.id === variantId);
 | 
						|
        if (!variant) return {};
 | 
						|
 | 
						|
        const values = {};
 | 
						|
        
 | 
						|
        // Get constants
 | 
						|
        variant.constants.forEach(constant => {
 | 
						|
            const element = document.getElementById(constant.id);
 | 
						|
            if (element) {
 | 
						|
                values[constant.id] = parseHex(element.value) || 0;
 | 
						|
            }
 | 
						|
        });
 | 
						|
 | 
						|
        // Get inputs
 | 
						|
        variant.inputs.forEach(input => {
 | 
						|
            const element = document.getElementById(input.id);
 | 
						|
            if (element) {
 | 
						|
                values[input.id] = parseHex(element.value);
 | 
						|
            }
 | 
						|
        });
 | 
						|
 | 
						|
        return values;
 | 
						|
    }
 | 
						|
} |