Rekenmachine Maken Html

HTML Rekenmachine Maker

Maak een professionele HTML-calculator met deze interactieve tool. Vul de velden in en genereer direct de code.

Resultaten

Geschatte ontwikkeltijd:
Complexiteitsniveau:
Aanbevolen technologie:
HTML Code:
CSS Code:
JavaScript Code:

De Ultieme Gids voor het Maken van een HTML Rekenmachine

Een HTML rekenmachine maken is een uitstekend project voor zowel beginnende als gevorderde webontwikkelaars. Het combineert HTML-structuur, CSS-styling en JavaScript-functionaliteit in één praktisch toepasbaar product. In deze uitgebreide gids leer je stap voor stap hoe je verschillende soorten rekenmachines kunt bouwen, van eenvoudige basisrekenmachines tot geavanceerde financiële calculators.

Waarom een HTML Rekenmachine Bouwen?

Er zijn verschillende redenen waarom het bouwen van een HTML rekenmachine een waardevol project is:

  • Leerervaring: Het helpt je de kernconcepten van webontwikkeling te begrijpen en toe te passen.
  • Praktisch nut: Je kunt het direct implementeren op websites voor verschillende doeleinden.
  • Portfolio-opbouw: Een goed ontworpen rekenmachine demonstreert je vaardigheden aan potentiële werkgevers.
  • Aanpasbaarheid: Je kunt het aanpassen voor specifieke behoeften zoals financiële berekeningen, wetenschappelijke functies of conversies.
  • Interactiviteit: Het is een uitstekende manier om te leren hoe je gebruikersinput kunt verwerken en dynamische resultaten kunt tonen.

De Basisstructuur van een HTML Rekenmachine

Elke HTML rekenmachine bestaat uit drie hoofdcomponenten:

  1. HTML: Definieert de structuur en elementen van de rekenmachine (display, knoppen, etc.)
  2. CSS: Zorgt voor de visuele stijl en lay-out
  3. JavaScript: Voegt de functionaliteit toe en verwerkt de berekeningen

1. HTML Structuur

De HTML-structuur vormt het skelet van je rekenmachine. Hier is een basisvoorbeeld:

<div class="calculator">
    <div class="display">
        <div class="previous-operand"></div>
        <div class="current-operand">0</div>
    </div>

    <button class="span-two">AC</button>
    <button>DEL</button>
    <button>÷</button>
    <button>1</button>
    <button>2</button>
    <button>3</button>
    <button>×</button>
    <button>4</button>
    <button>5</button>
    <button>6</button>
    <button>+</button>
    <button>7</button>
    <button>8</button>
    <button>9</button>
    <button>-</button>
    <button>.</button>
    <button>0</button>
    <button class="span-two">=</button>
</div>

2. CSS Styling

CSS bepaalt hoe je rekenmachine eruitziet. Hier is een basisstijl:

.calculator {
    width: 100%;
    max-width: 400px;
    margin: 0 auto;
    border: 1px solid #ccc;
    border-radius: 10px;
    padding: 20px;
    background-color: #f9f9f9;
}

.display {
    background-color: #252525;
    color: white;
    padding: 20px;
    border-radius: 5px;
    margin-bottom: 20px;
    text-align: right;
    word-wrap: break-word;
    min-height: 60px;
}

.previous-operand {
    color: rgba(255, 255, 255, 0.7);
    font-size: 1rem;
}

.current-operand {
    color: white;
    font-size: 2rem;
}

button {
    width: 60px;
    height: 60px;
    border: none;
    border-radius: 5px;
    margin: 5px;
    font-size: 1.2rem;
    cursor: pointer;
    background-color: #e0e0e0;
    transition: background-color 0.2s;
}

button:hover {
    background-color: #d0d0d0;
}

button:active {
    background-color: #b0b0b0;
}

.span-two {
    width: 130px;
}

.operator {
    background-color: #ff9500;
    color: white;
}

.operator:hover {
    background-color: #e68a00;
}

.operator:active {
    background-color: #cc7a00;
}

3. JavaScript Functionaliteit

JavaScript maakt de rekenmachine functioneel. Hier is een basisimplementatie:

class Calculator {
    constructor(previousOperandTextElement, currentOperandTextElement) {
        this.previousOperandTextElement = previousOperandTextElement;
        this.currentOperandTextElement = currentOperandTextElement;
        this.clear();
    }

    clear() {
        this.currentOperand = '0';
        this.previousOperand = '';
        this.operation = undefined;
    }

    delete() {
        this.currentOperand = this.currentOperand.toString().slice(0, -1);
        if (this.currentOperand === '') {
            this.currentOperand = '0';
        }
    }

    appendNumber(number) {
        if (number === '.' && this.currentOperand.includes('.')) return;
        if (this.currentOperand === '0' && number !== '.') {
            this.currentOperand = number.toString();
        } else {
            this.currentOperand = this.currentOperand.toString() + number.toString();
        }
    }

    chooseOperation(operation) {
        if (this.currentOperand === '') return;
        if (this.previousOperand !== '') {
            this.compute();
        }
        this.operation = operation;
        this.previousOperand = this.currentOperand;
        this.currentOperand = '';
    }

    compute() {
        let computation;
        const prev = parseFloat(this.previousOperand);
        const current = parseFloat(this.currentOperand);
        if (isNaN(prev) || isNaN(current)) return;

        switch (this.operation) {
            case '+':
                computation = prev + current;
                break;
            case '-':
                computation = prev - current;
                break;
            case '×':
                computation = prev * current;
                break;
            case '÷':
                computation = prev / current;
                break;
            default:
                return;
        }

        this.currentOperand = computation;
        this.operation = undefined;
        this.previousOperand = '';
    }

    updateDisplay() {
        this.currentOperandTextElement.innerText = this.currentOperand;
        if (this.operation != null) {
            this.previousOperandTextElement.innerText =
                `${this.previousOperand} ${this.operation}`;
        } else {
            this.previousOperandTextElement.innerText = '';
        }
    }
}

const numberButtons = document.querySelectorAll('[data-number]');
const operationButtons = document.querySelectorAll('[data-operation]');
const equalsButton = document.querySelector('[data-equals]');
const deleteButton = document.querySelector('[data-delete]');
const allClearButton = document.querySelector('[data-all-clear]');
const previousOperandTextElement = document.querySelector('[data-previous-operand]');
const currentOperandTextElement = document.querySelector('[data-current-operand]');

const calculator = new Calculator(previousOperandTextElement, currentOperandTextElement);

numberButtons.forEach(button => {
    button.addEventListener('click', () => {
        calculator.appendNumber(button.innerText);
        calculator.updateDisplay();
    });
});

operationButtons.forEach(button => {
    button.addEventListener('click', () => {
        calculator.chooseOperation(button.innerText);
        calculator.updateDisplay();
    });
});

equalsButton.addEventListener('click', () => {
    calculator.compute();
    calculator.updateDisplay();
});

allClearButton.addEventListener('click', () => {
    calculator.clear();
    calculator.updateDisplay();
});

deleteButton.addEventListener('click', () => {
    calculator.delete();
    calculator.updateDisplay();
});

Geavanceerde Functionaliteiten Toevoegen

Een basisrekenmachine is een goed begin, maar je kunt veel geavanceerdere functionaliteiten toevoegen:

1. Wetenschappelijke Functies

Voor een wetenschappelijke rekenmachine kun je functies toevoegen zoals:

  • Sin, Cos, Tan en hun inverse functies
  • Logaritmen (log, ln)
  • Exponentiële functies (e^x, x^y)
  • Wortel en n-de machtswortel
  • Factoriëlen en permutaties
  • Constantes zoals π en e

Hier is een voorbeeld van hoe je de sinus-functie kunt implementeren:

sin() {
    const current = parseFloat(this.currentOperand);
    if (isNaN(current)) return;

    // Convert degrees to radians if needed
    const inRadians = this.degreeMode ? current * Math.PI / 180 : current;
    this.currentOperand = Math.sin(inRadians);

    if (this.degreeMode) {
        this.currentOperand = Math.sin(current * Math.PI / 180);
    } else {
        this.currentOperand = Math.sin(current);
    }
}

2. Financiële Berekeningen

Voor financiële rekenmachines kun je functies toevoegen zoals:

  • Enkelvoudige en samengestelde interest
  • Leningberekeningen (maandelijkse betalingen, totale rente)
  • Netto contante waarde (NPV) en interne opbrengstvoet (IRR)
  • Valutaconversies
  • Beleggingsgroei berekeningen

Hier is een voorbeeld van een leningberekening:

calculateLoan(principal, rate, years) {
    const monthlyRate = rate / 100 / 12;
    const payments = years * 12;
    const x = Math.pow(1 + monthlyRate, payments);
    const monthly = (principal * x * monthlyRate) / (x - 1);

    return {
        monthlyPayment: monthly,
        totalPayment: monthly * payments,
        totalInterest: (monthly * payments) - principal
    };
}

3. Grafische Weergave

Je kunt je rekenmachine uitbreiden met grafische weergaves using libraries zoals Chart.js. Dit is vooral nuttig voor:

  • Het plotten van wiskundige functies
  • Het visualiseren van financiële gegevens
  • Het tonen van statistische distribities
  • Het weergeven van historische gegevens

Hier is een basisvoorbeeld met Chart.js:

function plotFunction(fn, min, max) {
    const ctx = document.getElementById('functionChart').getContext('2d');

    // Generate data points
    const step = (max - min) / 100;
    const labels = [];
    const data = [];

    for (let x = min; x <= max; x += step) {
        labels.push(x.toFixed(2));
        data.push(fn(x));
    }

    new Chart(ctx, {
        type: 'line',
        data: {
            labels: labels,
            datasets: [{
                label: 'f(x)',
                data: data,
                borderColor: 'rgb(75, 192, 192)',
                tension: 0.1
            }]
        },
        options: {
            responsive: true,
            scales: {
                x: { title: { display: true, text: 'x' } },
                y: { title: { display: true, text: 'f(x)' } }
            }
        }
    });
}

// Example usage for f(x) = x^2
plotFunction(x => Math.pow(x, 2), -10, 10);

Optimalisatie en Beste Praktijken

Bij het bouwen van een HTML rekenmachine zijn er verschillende beste praktijken om in gedachten te houden:

1. Responsiviteit

Zorg ervoor dat je rekenmachine goed werkt op alle apparaten:

  • Gebruik media queries om de lay-out aan te passen voor kleinere schermen
  • Pas de knopgrootte aan voor touchscreens
  • Zorg voor voldoende ruimte tussen knoppen voor gemakkelijk tikken
  • Gebruik relatieve eenheden (%, vw, vh) waar mogelijk
@media (max-width: 600px) {
    .calculator {
        max-width: 100%;
        padding: 10px;
    }

    button {
        width: 50px;
        height: 50px;
        font-size: 1rem;
    }

    .span-two {
        width: 110px;
    }
}

2. Toegankelijkheid

Maak je rekenmachine toegankelijk voor alle gebruikers:

  • Voeg ARIA-labels toe aan knoppen
  • Zorg voor voldoende kleurcontrast
  • Voeg keyboard navigatie toe
  • Gebruik semantische HTML
  • Voeg focus states toe voor toetsenbordgebruikers
button {
    /* ... andere stijlen ... */
    &:focus {
        outline: 2px solid #2563eb;
        outline-offset: 2px;
    }
}

[aria-label] {
    position: relative;
}

[aria-label]:after {
    content: attr(aria-label);
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    background: #333;
    color: white;
    padding: 2px 6px;
    border-radius: 3px;
    font-size: 0.8rem;
    opacity: 0;
    transition: opacity 0.2s;
    pointer-events: none;
    white-space: nowrap;
}

[aria-label]:hover:after {
    opacity: 1;
}

3. Prestatie Optimalisatie

Optimaliseer de prestaties van je rekenmachine:

  • Minimaliseer DOM-manipulaties
  • Gebruik event delegation voor knoppen
  • Debounce of throttle events waar nodig
  • Gebruik efficiënte algoritmes voor complexe berekeningen
  • Implementeer caching voor herhaalde berekeningen
// Event delegation voor alle knoppen
document.querySelector('.calculator').addEventListener('click', (e) => {
    if (e.target.matches('button')) {
        const button = e.target;
        const action = button.dataset.action;
        const value = button.dataset.value;

        // Verwerk de actie op basis van de knop
        if (action === 'number') {
            calculator.appendNumber(value);
        } else if (action === 'operation') {
            calculator.chooseOperation(value);
        }
        // ... andere acties ...

        calculator.updateDisplay();
    }
});

// Memoization voor dure berekeningen
const memoize = (fn) => {
    const cache = new Map();
    return (...args) => {
        const key = JSON.stringify(args);
        if (cache.has(key)) {
            return cache.get(key);
        }
        const result = fn.apply(this, args);
        cache.set(key, result);
        return result;
    };
};

const expensiveCalculation = memoize((x) => {
    // Dure berekening hier
    return complexAlgorithm(x);
});

Veelgemaakte Fouten en Hoe Ze te Vermijden

Bij het bouwen van HTML rekenmachines worden vaak dezelfde fouten gemaakt. Hier zijn de meest voorkomende en hoe je ze kunt vermijden:

Fout Probleem Oplossing
Geen input validatie Gebruikers kunnen ongeldige tekens invoeren die de rekenmachine kunnen crashen Implementeer strikte input validatie en sanitatie. Gebruik reguliere expressies om alleen toegestane tekens toe te staan.
Drijvende komma nauwkeurigheid JavaScript heeft beperkingen in het nauwkeurig weergeven van decimale getallen (bv. 0.1 + 0.2 = 0.30000000000000004) Gebruik een bibliotheek zoals decimal.js voor nauwkeurige decimale berekeningen of rond af op een redelijk aantal decimalen.
Geen error handling De rekenmachine crasht bij onverwachte inputs zoals deling door nul Implementeer try-catch blokken en toon gebruiksvriendelijke foutmeldingen.
Slechte staatbeheer De rekenmachine “vergeet” zijn staat bij complexe berekeningen Gebruik een duidelijke staatstructuur (bv. een class zoals in het voorbeeld) om alle benodigde informatie bij te houden.
Onvoldoende testen De rekenmachine werkt niet voor randgevallen of complexe berekeningen Schrijf uitgebreide tests die alle functionaliteit dekken, inclusief randgevallen.
Slechte prestaties De rekenmachine voelt traag aan bij complexe berekeningen Optimaliseer je code, gebruik memoization voor dure berekeningen en implementeer efficiënte algoritmes.

Geavanceerde Technieken

Voor echt professionele rekenmachines kun je geavanceerdere technieken implementeren:

1. Reverse Polish Notation (RPN)

RPN, ook bekend als postfix notatie, is een wiskundige notatie waarin elke operator volgt op al zijn operanden. Dit elimineert de behoefte aan haakjes om de volgorde van bewerkingen te bepalen.

Implementatie:

class RPNCalculator {
    constructor() {
        this.stack = [];
    }

    push(value) {
        this.stack.push(parseFloat(value));
    }

    performOperation(operator) {
        if (this.stack.length < 2) return;

        const b = this.stack.pop();
        const a = this.stack.pop();
        let result;

        switch(operator) {
            case '+': result = a + b; break;
            case '-': result = a - b; break;
            case '×': result = a * b; break;
            case '÷':
                if (b === 0) throw new Error("Division by zero");
                result = a / b;
                break;
            case '^': result = Math.pow(a, b); break;
            default: throw new Error("Unknown operator");
        }

        this.stack.push(result);
    }

    getResult() {
        if (this.stack.length !== 1) {
            throw new Error("Invalid expression");
        }
        return this.stack[0];
    }
}

2. Symbolische Wiskunde

Voor echt geavanceerde rekenmachines kun je symbolische wiskunde implementeren met bibliotheken zoals math.js. Dit stelt gebruikers in staat om:

  • Werk te doen met symbolen en variabelen
  • Vergelijkingen op te lossen
  • Functies te differentiëren en integreren
  • Met matrices te werken
// Voorbeeld met math.js
const math = require('mathjs');

const expr = math.parse('sqrt(4 + x^2)');
const code = expr.compile();
const x = 3;
const y = code.evaluate({x: x}); // returns 3.605551275463989

// Oplossen van vergelijkingen
const solution = math.solve('x^2 + 2x - 4 = 0', 'x');
// returns [-1 - sqrt(5), -1 + sqrt(5)]

// Differentiëren
const derivative = math.derivative('x^2 + 3x + 4', 'x');
// returns Node {op: 'FunctionNode', fn: 'derivative'}

3. Offline Functionaliteit

Maak je rekenmachine beschikbaar zonder internetverbinding:

  • Gebruik Service Workers om assets te cachen
  • Implementeer een Progressive Web App (PWA)
  • Gebruik IndexedDB voor het opslaan van berekeningsgeschiedenis
  • Implementeer een cache-first strategie voor snellere laadtijden
// service-worker.js
const CACHE_NAME = 'calculator-v1';
const urlsToCache = [
    '/',
    '/index.html',
    '/styles.css',
    '/script.js',
    'https://cdn.jsdelivr.net/npm/mathjs@9.4.4/lib/browser/math.js'
];

self.addEventListener('install', event => {
    event.waitUntil(
        caches.open(CACHE_NAME)
            .then(cache => {
                return cache.addAll(urlsToCache);
            })
    );
});

self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request)
            .then(response => {
                if (response) {
                    return response;
                }
                return fetch(event.request);
            })
    );
});

Inspiratie: 5 Creatieve Rekenmachine Concepten

Hier zijn vijf unieke rekenmachine concepten die je kunt bouwen met HTML, CSS en JavaScript:

  1. Kookrekenmachine:

    Een rekenmachine die helpt bij het omrekenen van ingrediënten, kooktijden en temperaturen. Inclusief functies voor:

    • Omrekenen van cups naar gram
    • Aanpassen van recepten voor verschillende porties
    • Omrekenen van Fahrenheit naar Celsius
    • Berekenen van kooktijden op basis van gewicht
  2. Fitness Rekenmachine:

    Een rekenmachine voor fitnessdoeleinden met functies zoals:

    • BMI berekening
    • Caloriebehoefte (BMR en TDEE)
    • Macro verdeling (koolhydraten, eiwitten, vetten)
    • 1RM (One Rep Max) calculator
    • Voortgangstracking met grafieken
  3. Cryptocurrency Rekenmachine:

    Een rekenmachine voor cryptocurrency handel met:

    • Realtime prijsconversies
    • Winst/verlies berekeningen
    • Mining profitability calculator
    • Portfolio waarde tracking
    • Historische prijsgrafieken
  4. Tijdreizen Rekenmachine:

    Een leuke rekenmachine die "berekent" wat er zou zijn gebeurd als je in het verleden had geïnvesteerd:

    • Bereken wat $100 in 1980 waard zou zijn vandaag
    • Vergelijk historische inflatie
    • Simuleer beleggingsgroei over tijd
    • Toon historische gebeurtenissen op belangrijke data
  5. Duurzaamheidsrekenmachine:

    Een rekenmachine die helpt bij het berekenen van milieueffecten:

    • CO2 voetafdruk calculator
    • Energiekosten en besparingen
    • Waterverbruik analyse
    • Afvalrecycling impact
    • Duurzame investeringsopties

Tools en Bibliotheken voor Rekenmachine Ontwikkeling

Er zijn verschillende tools en bibliotheken die het bouwen van rekenmachines gemakkelijker en krachtiger kunnen maken:

Tool/Bibliotheek Beschrijving Gebruiksscenario Website
Math.js Een uitgebreide bibliotheek voor wiskundige berekeningen Geavanceerde wiskundige functies, symbolische berekeningen, eenheden conversie mathjs.org
Chart.js Een eenvoudige maar flexibele JavaScript bibliotheek voor grafieken Visualisatie van berekeningsresultaten, historische data, statistische distribities chartjs.org
Decimal.js Een bibliotheek voor arbitraire precisie decimale rekenkunde Financiële berekeningen waar nauwkeurigheid cruciaal is mikemcl.github.io/decimal.js
Algebrite Een computer algebra systeem in JavaScript Symbolische wiskunde, vergelijkingen oplossen, calculus algebrite.org
Numeral.js Een bibliotheek voor het formateren en manipuleren van getallen Mooi formateren van grote getallen, valuta formattering numeraljs.com
Big.js Een bibliotheek voor arbitraire precisie decimale rekenkunde Financiële berekeningen met hoge precisie mikemcl.github.io/big.js
Fraction.js Een bibliotheek voor rationele getallen (breuken) Berekeningen met breuken, exacte wiskunde github.com/infusion/Fraction.js

Testen en Debuggen

Het testen en debuggen van je rekenmachine is essentieel voor een betrouwbaar product. Hier zijn enkele strategieën:

1. Unit Testing

Schrijf tests voor individuele functies:

// Voorbeeld met Jest
test('adds 1 + 2 to equal 3', () => {
    const calculator = new Calculator();
    calculator.appendNumber('1');
    calculator.chooseOperation('+');
    calculator.appendNumber('2');
    calculator.compute();
    expect(calculator.currentOperand).toBe('3');
});

test('handles division by zero', () => {
    const calculator = new Calculator();
    calculator.appendNumber('5');
    calculator.chooseOperation('÷');
    calculator.appendNumber('0');
    expect(() => calculator.compute()).toThrow('Division by zero');
});

2. Integratie Testing

Test de interactie tussen verschillende componenten:

// Voorbeeld met Cypress
describe('Calculator Integration', () => {
    it('performs a complete calculation', () => {
        cy.visit('/calculator.html');

        cy.get('[data-value="7"]').click();
        cy.get('[data-operation="+"]').click();
        cy.get('[data-value="8"]').click();
        cy.get('[data-equals]').click();

        cy.get('[data-current-operand]').should('contain', '15');
    });

    it('handles clear button', () => {
        cy.get('[data-value="9"]').click();
        cy.get('[data-all-clear]').click();
        cy.get('[data-current-operand]').should('contain', '0');
    });
});

3. Gebruikerstesten

Laat echte gebruikers je rekenmachine testen en verzamel feedback:

  • Organiseer gebruikerssessies met verschillende demografische groepen
  • Gebruik tools zoals Hotjar om gebruikersgedrag te analyseren
  • Verzamel feedback over de gebruikerservaring
  • Test op verschillende apparaten en browsers
  • Analyseer veelgemaakte fouten en verbeter de interface

4. Prestatietesten

Meet en optimaliseer de prestaties:

  • Gebruik Chrome DevTools om prestatieknelpunten te identificeren
  • Test met grote inputs om memory leaks te detecteren
  • Meet de reactietijd van de interface
  • Optimaliseer kritieke codepaden
  • Gebruik Lighthouse voor algemene prestatie-audits
Autoritatieve Bronnen:

Voor meer technische informatie over het bouwen van web-based rekenmachines, raadpleeg deze autoritatieve bronnen:

Conclusie

Het bouwen van een HTML rekenmachine is een uitstekende manier om je vaardigheden in webontwikkeling te verbeteren. Begin met een eenvoudige basisrekenmachine en breid deze geleidelijk uit met geavanceerdere functionaliteiten naarmate je meer ervaring opdoet.

Onthoud deze sleutelprincipes:

  1. Begin met een duidelijke specificatie van wat je wilt bereiken
  2. Bouw de functionaliteit stap voor stap op
  3. Test elke nieuwe functie grondig
  4. Optimaliseer voor zowel prestaties als gebruikerservaring
  5. Maak je code onderhoudbaar en goed gedocumenteerd
  6. Blijf leren en experimenteer met nieuwe technieken

Met de kennis uit deze gids ben je goed uitgerust om professionele, functionele en visueel aantrekkelijke HTML rekenmachines te bouwen die voldoen aan de behoeften van verschillende gebruikers.

Veel succes met je rekenmachine project! Als je vastloopt of specifieke vragen hebt, aarzel dan niet om de documentatie van de genoemde bibliotheken te raadplegen of deel te nemen aan ontwikkelaarscommunities voor hulp en inspiratie.

`; } function generateCSSCode(colorScheme, buttonStyle, responsive, customCSS) { // Base colors for different schemes const colorSchemes = { blue: { background: '#f8fafc', display: '#252525', buttons: '#e2e8f0', operators: '#3b82f6', equals: '#1d4ed8', text: '#1e293b', border: '#cbd5e1' }, green: { background: '#f0fdf4', display: '#166534', buttons: '#d1fae5', operators: '#10b981', equals: '#059669', text: '#065f46', border: '#a7f3d0' }, purple: { background: '#faf5ff', display: '#581c87', buttons: '#e9d5ff', operators: '#8b5cf6', equals: '#7c3aed', text: '#581c87', border: '#c4b5fd' }, dark: { background: '#1e293b', display: '#0f172a', buttons: '#334155', operators: '#60a5fa', equals: '#3b82f6', text: '#f8fafc', border: '#475569' }, light: { background: '#ffffff', display: '#1e293b', buttons: '#f1f5f9', operators: '#64748b', equals: '#475569', text: '#0f172a', border: '#e2e8f0' } }; const colors = colorSchemes[colorScheme]; // Button style variations const buttonStyles = { flat: ` button { box-shadow: none; border: 1px solid ${colors.border}; } `, '3d': ` button { box-shadow: 0 4px 0 ${darkenColor(colors.buttons, 20)}; transition: box-shadow 0.1s, transform 0.1s; } button:active { box-shadow: 0 1px 0 ${darkenColor(colors.buttons, 20)}; transform: translateY(3px); } `, rounded: ` button { border-radius: 50%; aspect-ratio: 1/1; } .span-two { border-radius: 2rem; } `, outline: ` button { background-color: transparent; border: 2px solid ${colors.operators}; color: ${colors.operators}; } button[data-operation], button[data-equals] { background-color: ${colors.operators}; color: white; } ` }; // Generate responsive CSS if enabled const responsiveCSS = responsive === 'yes' ? `@media (max-width: 600px) { .calculator { max-width: 100%; padding: 0.5rem; } .grid { grid-template-columns: repeat(4, 1fr); gap: 0.25rem; } button { padding: 0.5rem; font-size: 0.875rem; } }` : ''; return `/* Base Styles */ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background-color: ${colors.background}; color: ${colors.text}; margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; min-height: 100vh; } .calculator { background-color: ${colors.background}; border-radius: 10px; padding: 1.5rem; box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); width: 100%; max-width: 400px; } .display { background-color: ${colors.display}; color: white; padding: 1rem; border-radius: 5px; margin-bottom: 1rem; text-align: right; word-wrap: break-word; min-height: 2rem; display: flex; flex-direction: column; justify-content: flex-end; } .previous-operand { color: rgba(255, 255, 255, 0.7); font-size: 1rem; min-height: 1.2rem; } .current-operand { color: white; font-size: 2rem; min-height: 2rem; } .history { color: rgba(255, 255, 255, 0.5); font-size: 0.875rem; min-height: 1rem; margin-bottom: 0.5rem; } .grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.5rem; } /* Button Styles */ button { border: none; border-radius: 5px; height: 3rem; font-size: 1.25rem; cursor: pointer; transition: all 0.2s; background-color: ${colors.buttons}; color: ${colors.text}; } button:hover { opacity: 0.9; } button:active { opacity: 0.7; } button[data-operation] { background-color: ${colors.operators}; color: white; } button[data-equals] { background-color: ${colors.equals}; color: white; } /* Memory Button Styles */ button[data-memory] { background-color: ${darkenColor(colors.buttons, 10)}; font-size: 1rem; } /* Specific Button Styles */ ${buttonStyles[buttonStyle]} ${responsiveCSS} /* Custom CSS */ ${customCSS} /* Helper function for darkening colors (used in JS) */ function darkenColor(color, percent) { // This would be implemented in the actual CSS generation // For this example, we'll return a placeholder return '#darkened-color'; } `; } function generateJSCode(type, includeMemory) { let calculatorClass = ''; let additionalFunctions = ''; switch(type) { case 'basic': calculatorClass = `class Calculator { constructor(previousOperandTextElement, currentOperandTextElement) { this.previousOperandTextElement = previousOperandTextElement; this.currentOperandTextElement = currentOperandTextElement; this.clear(); } clear() { this.currentOperand = '0'; this.previousOperand = ''; this.operation = undefined; } delete() { this.currentOperand = this.currentOperand.toString().slice(0, -1); if (this.currentOperand === '') { this.currentOperand = '0'; } } appendNumber(number) { if (number === '.' && this.currentOperand.includes('.')) return; if (this.currentOperand === '0' && number !== '.') { this.currentOperand = number.toString(); } else { this.currentOperand = this.currentOperand.toString() + number.toString(); } } chooseOperation(operation) { if (this.currentOperand === '') return; if (this.previousOperand !== '') { this.compute(); } this.operation = operation; this.previousOperand = this.currentOperand; this.currentOperand = ''; } compute() { let computation; const prev = parseFloat(this.previousOperand); const current = parseFloat(this.currentOperand); if (isNaN(prev) || isNaN(current)) return; switch (this.operation) { case '+': computation = prev + current; break; case '-': computation = prev - current; break; case '×': computation = prev * current; break; case '÷': computation = prev / current; break; default: return; } this.currentOperand = computation; this.operation = undefined; this.previousOperand = ''; } updateDisplay() { this.currentOperandTextElement.innerText = this.currentOperand; if (this.operation != null) { this.previousOperandTextElement.innerText = \`\${this.previousOperand} \${this.operation}\`; } else { this.previousOperandTextElement.innerText = ''; } } }`; break; case 'advanced': calculatorClass = `class Calculator { constructor(previousOperandTextElement, currentOperandTextElement) { this.previousOperandTextElement = previousOperandTextElement; this.currentOperandTextElement = currentOperandTextElement; this.clear(); this.degreeMode = true; } clear() { this.currentOperand = '0'; this.previousOperand = ''; this.operation = undefined; } // ... (basic methods remain the same) ... performFunction(fn) { const current = parseFloat(this.currentOperand); if (isNaN(current)) return; let result; switch(fn) { case 'sin': result = this.degreeMode ? Math.sin(current * Math.PI / 180) : Math.sin(current); break; case 'cos': result = this.degreeMode ? Math.cos(current * Math.PI / 180) : Math.cos(current); break; case 'tan': result = this.degreeMode ? Math.tan(current * Math.PI / 180) : Math.tan(current); break; case 'sqrt': result = Math.sqrt(current); break; case 'pi': result = Math.PI; break; default: return; } this.currentOperand = result; } power() { if (this.previousOperand === '') return; const prev = parseFloat(this.previousOperand); const current = parseFloat(this.currentOperand); if (isNaN(prev) || isNaN(current)) return; this.currentOperand = Math.pow(prev, current); this.operation = undefined; this.previousOperand = ''; } }`; break; case 'financial': calculatorClass = `class Calculator { constructor(previousOperandTextElement, currentOperandTextElement) { this.previousOperandTextElement = previousOperandTextElement; this.currentOperandTextElement = currentOperandTextElement; this.clear(); } clear() { this.currentOperand = '0'; this.previousOperand = ''; this.operation = undefined; this.financialMode = null; this.financialValues = {}; } // ... (basic methods remain the same) ... setFinancialMode(mode) { this.financialMode = mode; this.financialValues = {}; this.currentOperand = '0'; } setFinancialValue(key) { if (!this.financialMode) return; const value = parseFloat(this.currentOperand); if (isNaN(value)) return; this.financialValues[key] = value; this.currentOperand = '0'; } calculateFinancial() { if (!this.financialMode) return; let result; switch(this.financialMode) { case 'pmt': // Monthly payment calculation const {principal, rate, years} = this.financialValues; const monthlyRate = rate / 100 / 12; const payments = years * 12; const x = Math.pow(1 + monthlyRate, payments); result = (principal * x * monthlyRate) / (x - 1); break; case 'ir': // Interest rate calculation would be more complex result = 'Complex calc'; break; default: return; } this.currentOperand = result.toFixed(2); this.financialMode = null; } }`; break; case 'conversion': calculatorClass = `class Calculator { constructor(previousOperandTextElement, currentOperandTextElement) { this.previousOperandTextElement = previousOperandTextElement; this.currentOperandTextElement = currentOperandTextElement; this.clear(); this.conversionType = null; this.fromUnit = null; this.toUnit = null; } clear() { this.currentOperand = '0'; this.previousOperand = ''; this.operation = undefined; this.conversionType = null; } // ... (basic methods remain the same) ... setConversionType(type) { this.conversionType = type; switch(type) { case 'temp': this.fromUnit = 'C'; this.toUnit = 'F'; break; case 'weight': this.fromUnit = 'kg'; this.toUnit = 'lb'; break; case 'length': this.fromUnit = 'm'; this.toUnit = 'ft'; break; case 'volume': this.fromUnit = 'L'; this.toUnit = 'gal'; break; case 'currency': this.fromUnit = 'EUR'; this.toUnit = 'USD'; break; } } swapConversion() { if (!this.conversionType) return; [this.fromUnit, this.toUnit] = [this.toUnit, this.fromUnit]; this.updateDisplay(); } convert() { if (!this.conversionType) return; const value = parseFloat(this.currentOperand); if (isNaN(value)) return; let result; switch(this.conversionType) { case 'temp': if (this.fromUnit === 'C') { result = (value * 9/5) + 32; // C to F } else { result = (value - 32) * 5/9; // F to C } break; case 'weight': if (this.fromUnit === 'kg') { result = value * 2.20462; // kg to lb } else { result = value / 2.20462; // lb to kg } break; case 'length': if (this.fromUnit === 'm') { result = value * 3.28084; // m to ft } else { result = value / 3.28084; // ft to m } break; case 'volume': if (this.fromUnit === 'L') { result = value * 0.264172; // L to gal } else { result = value / 0.264172; // gal to L } break; case 'currency': // In a real app, you would fetch current exchange rates if (this.fromUnit === 'EUR') { result = value * 1.07; // EUR to USD (example rate) } else { result = value / 1.07; // USD to EUR } break; } this.previousOperand = \`\${value} \${this.fromUnit}\`; this.currentOperand = \`\${result.toFixed(4)} \${this.toUnit}\`; } }`; break; } // Add memory functions if enabled if (includeMemory === 'yes') { additionalFunctions = ` // Memory functions let memoryValue = 0; function handleMemory(action) { const current = parseFloat(calculator.currentOperand); if (isNaN(current)) return; switch(action) { case 'store': memoryValue = current; break; case 'recall': calculator.currentOperand = memoryValue.toString(); calculator.updateDisplay(); break; case 'clear': memoryValue = 0; break; } } `; } return `${calculatorClass} /* DOM Element References */ const previousOperandTextElement = document.querySelector('[data-previous-operand]'); const currentOperandTextElement = document.querySelector('[data-current-operand]'); const historyTextElement = document.querySelector('[data-history]'); const calculator = new Calculator(previousOperandTextElement, currentOperandTextElement); /* Event Listeners */ document.querySelectorAll('[data-number]').forEach(button => { button.addEventListener('click', () => { calculator.appendNumber(button.innerText); calculator.updateDisplay(); }); }); document.querySelectorAll('[data-operation]').forEach(button => { button.addEventListener('click', () => { calculator.chooseOperation(button.innerText); calculator.updateDisplay(); }); }); document.querySelector('[data-equals]').addEventListener('click', () => { calculator.compute(); calculator.updateDisplay(); }); document.querySelector('[data-all-clear]').addEventListener('click', () => { calculator.clear(); calculator.updateDisplay(); }); document.querySelector('[data-delete]').addEventListener('click', () => { calculator.delete(); calculator.updateDisplay(); }); /* Additional function handlers based on calculator type */ ${getAdditionalEventListeners(type)} /* Memory function handlers */ ${includeMemory === 'yes' ? ` document.querySelectorAll('[data-memory]').forEach(button => { button.addEventListener('click', () => { handleMemory(button.dataset.memory); }); }); ` : ''} /* Initial display update */ calculator.updateDisplay(); ${additionalFunctions} function ${getAdditionalFunctions(type)} { // Additional functions would be implemented here // based on the calculator type } function getAdditionalEventListeners(type) { switch(type) { case 'advanced': return \` document.querySelectorAll('[data-function]').forEach(button => { button.addEventListener('click', () => { if (button.dataset.function === 'pi') { calculator.currentOperand = Math.PI.toString(); } else { calculator.performFunction(button.dataset.function); } calculator.updateDisplay(); }); }); document.querySelector('[data-operation="^"]').addEventListener('click', () => { calculator.operation = '^'; calculator.previousOperand = calculator.currentOperand; calculator.currentOperand = ''; calculator.updateDisplay(); }); \`; case 'financial': return \` document.querySelectorAll('[data-financial]').forEach(button => { button.addEventListener('click', () => { calculator.setFinancialMode(button.dataset.financial); }); }); document.querySelectorAll('[data-number]').forEach(button => { button.addEventListener('click', () => { if (calculator.financialMode) { // In financial mode, numbers are used to set values calculator.appendNumber(button.innerText); calculator.updateDisplay(); } else { // Normal operation calculator.appendNumber(button.innerText); calculator.updateDisplay(); } }); }); document.querySelector('[data-operation]').addEventListener('click', () => { if (calculator.financialMode) { // In financial mode, operations might set values const key = button.dataset.operation === '+' ? 'principal' : button.dataset.operation === '-' ? 'rate' : 'years'; calculator.setFinancialValue(key); } else { // Normal operation calculator.chooseOperation(button.innerText); calculator.updateDisplay(); } }); document.querySelector('[data-equals]').addEventListener('click', () => { if (calculator.financialMode) { calculator.calculateFinancial(); calculator.updateDisplay(); } else { calculator.compute(); calculator.updateDisplay(); } }); \`; case 'conversion': return \` document.querySelectorAll('[data-conversion]').forEach(button => { button.addEventListener('click', () => { calculator.setConversionType(button.dataset.conversion); calculator.updateDisplay(); }); }); document.querySelector('[data-action="swap"]').addEventListener('click', () => { calculator.swapConversion(); }); document.querySelector('[data-equals]').addEventListener('click', () => { calculator.convert(); calculator.updateDisplay(); }); \`; default: return ''; } } function getAdditionalFunctions(type) { // This would return additional helper functions based on calculator type return ''; } `; } function getTitle(type) { const titles = { basic: "Basis Rekenmachine", advanced: "Wetenschappelijke Rekenmachine", financial: "Financiële Rekenmachine", conversion: "Conversie Rekenmachine" }; return titles[type] || "HTML Rekenmachine"; } function updateChart(calculatorType, data) { const ctx = chartCanvas.getContext('2d'); // Destroy previous chart if it exists if (window.calculatorChart) { window.calculatorChart.destroy(); } window.calculatorChart = new Chart(ctx, { type: 'bar', data: { labels: ['Ontwikkeltijd (uren)', 'Complexiteit (1-10)', 'JS Regels'], datasets: [{ label: 'Rekenmachine Complexiteit', data: [data.devTime, data.complexity, data.jsLines], backgroundColor: [ 'rgba(37, 99, 235, 0.7)', 'rgba(59, 130, 246, 0.7)', 'rgba(29, 78, 216, 0.7)' ], borderColor: [ 'rgba(37, 99, 235, 1)', 'rgba(59, 130, 246, 1)', 'rgba(29, 78, 216, 1)' ], borderWidth: 1 }] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: true, max: Math.max(data.devTime, data.complexity, data.jsLines) + 2 } }, plugins: { title: { display: true, text: \`Complexiteit Analyse: \${getTitle(calculatorType)}\`, font: { size: 16 } }, legend: { display: false } } } }); } // Helper function to darken colors (simplified for this example) function darkenColor(color, percent) { // This is a simplified version - in a real implementation you would // parse the color and adjust its components return '#darkened-' + color.substring(1); } });

Leave a Reply

Your email address will not be published. Required fields are marked *