Aplikacja Kalkulator

0

Witam, wykonuje proste ćwiczenie tzn kalkulator i zablokowałem się. Chce zrobić symulator zwykłego kalkulatora z guzikami. Nie potrafię jednak wymyślić obsługi zdarzeń. Powinno być kliknięcie guzika -> kolejne kliknięcie i wynik, po każdym kliknięciu liczba winna ukazywać się na wyświetlaczu. Jak powiedzieć komputerowi by jedno zdarzenie "click" następowało po drugim i dopiero po drugim zwracało wynik.

document.addEventListener("DOMContentLoaded", 
    function() {
        const buttonsIdNames = 
        [
            'one', 'two', 'three', 'four', 
            'five', 'six', 'seven', 'eight', 
            'nine', 'zero', 'plus', 'minus', 
            'multi', 'divide', 'dot', 'result'
        ];
        buttonsIdNames.forEach(element => { 
            clickNumberToDisplay(element);
        });
    }
);
function clickNumberToDisplay(id) {
    const button = document.getElementById(id);
    button.addEventListener("click", 
        function() {
            const numberToDisplay = parseInt(button.value);
            const display = document.getElementById('main-display');

            if(!isNaN(numberToDisplay)) {
                display.value = numberToDisplay; 
            };
        }
    );
}

A tu jest GUI w HTML-u :)

 <body>
        <div class="container">
            <div class="row">
                <div class="col-12">
                    <h1>CALC 0.3</h1>
                </div>
            </div>
        </div>
        <div class="container" id="main-wrapper">
            <div class="row">
                <div class="col-12 nopadding">
                    <input type="text" class="form-control" readonly value="0" id="main-display" />
                </div>
            </div>
            <div class="row">
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-primary" value="1" id="one" />
                </div>
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-primary" value="2" id="two" />
                </div>
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-primary" value="3" id="three" />
                </div>
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-success" value="+" id="plus" />
                </div>
            </div>
            <div class="row">
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-primary" value="4" id="four" />
                </div>
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-primary" value="5" id="five" />
                </div>
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-primary" value="6" id="six" />
                </div>
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-success" value="-" id="minus" />
                </div>
            </div>
            <div class="row">
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-primary" value="7" id="seven" />
                </div>
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-primary" value="8" id="eight" />
                </div>
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-primary" value="9" id="nine" />
                </div>
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-success" value="x" id="multi" />
                </div>
            </div>
            <div class="row">
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-primary" value="0" id="zero" />
                </div>
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-success" value="." id="dot" />
                </div>
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-success" value="/" id="divide" />
                </div>
                <div class="col-3 nopadding">
                    <input type="button" class="btn btn-outline-danger" value="=" id="result" />
                </div>
            </div>
        </div>
    </body>

Proszę o podpowiedź :)

0

Zdarzenia nie 'następują po sobie tak ot', są wywoływane konkretną akcją (tu - kliknięcie przycisku), i to działanie użytkownika narzuca im kolejność. To czego brakuje w Twoim programie to przechowywanie jakiegoś rodzaju stanu w sensowny sposób, np.

display.value = numberToDisplay; 

czemu np. nie dołączyć wklikanej nowo liczby do istniejącej wartości value?
Druga rzecz, musisz osobno obsługiwać przyciski od działań matematycznych. Tych nie zapisujesz na wyjściu - w momencie, gdy ktoś kliknie np znak '+', to zapamiętujesz, że plus był kliknięty, zapisujesz to, co było na wyjściu, czyścisz wyjście (wyświetlacz) i oczekujesz naciśnięcia kolejnego przycisku działania, albo '=' dla podania wyniku.

0

Nie jestem programistą o doświadczeniu zero a jednak mam problemy. Przeanalizowałem problem, muszą być trzy rzeczy (pobranie wyniku, wyczyszczenie wyświetlacza, zwiększenie wyniku):

1.Wyświetlacz jest ustawiony na zero, to jakiś tam input.
2.Tworzę zmienną, gdzie pobiorą wartość wyświetlacza po getElementById... itd.
-obsługa wpisywania danych z guzikami z liczbami jest zrobiona, jak klikam wychodzą liczby na wyświetlaczu.
3.Tworzę zmienną, by obsłużyć guzik dodać ten sposób po drzewie DOM wybieram element.
4.Wypisuje liczbę na wyświetlaczu
5.Klikam dodać.
6.Czyści mi wyświetlacz
7.Zapisuje argument liczbę z wyświetlacza do zmiennej.
8.Czeka na kolejną liczbę, do podania w wyświetlaczu.
9.Podaje liczbę.
10.Pobiera tę liczbę i zwiększa wcześniejszą zmienną o tę liczbę liczba += liczba_2
11.Naciśnięcie równa się daje wynik operacji.

Jak to wszystko napisać, problem wydaje się banalny a jakoś nie wiem...

1

Ugh, wyszło mi dużo bardziej skomplikowane, niż przypuszczałem, ale... działa https://jsfiddle.net/70o2pyvh/10/

Mimo to powinien być jakiś sensowniejszy sposób na to

Nie gwarantuję braku bugów

class SimpleCalc extends HTMLElement {
  constructor() {
    super()
    
    const shadow = this.attachShadow({mode: 'open'})
    shadow.innerHTML = `
    	<style>
      	:host {
          display: grid;
          grid-template-columns: repeat(4, 1fr);
          width: 200px;
        }
        
        input {
          grid-column: 1/5;
          text-align: right;
        }
        
        button {
          margin: 5px;
        }
      </style>
    
      <input id="scr" type="text">
    	<button class="dig">1</button>
      <button class="dig">2</button>
      <button class="dig">3</button>
      <button id="add">+</button>
      <button class="dig">4</button>
      <button class="dig">5</button>
      <button class="dig">6</button>
      <button id="sub">-</button>
      <button class="dig">7</button>
      <button class="dig">8</button>
      <button class="dig">9</button>
      <button id="mul">×</button>
      <button id="dec">.</button>
      <button class="dig">0</button>
      <button id="res">=</button>
      <button id="div">÷</button>
    `
    
    this.plus = (a, b) => a+b
    this.minus = (a, b) => a-b
    this.times = (a, b) => a*b
    this.by = (a, b) => a/b
    
    this.scr = shadow.querySelector("#scr")
    
    for(const dig of shadow.querySelectorAll(".dig"))
    	dig.onclick =
      	() => this.input_digit(parseInt(dig.textContent))
    
    shadow.querySelector("#dec").onclick =
    	() => this.input_decimal_separator()
    
    shadow.querySelector("#add").onclick =
    	() => this.input_addition(this.plus)
    shadow.querySelector("#sub").onclick =
    	() => this.input_addition(this.minus)
    shadow.querySelector("#mul").onclick =
    	() => this.input_multiplication(this.times)
    shadow.querySelector("#div").onclick =
    	() => this.input_multiplication(this.by)
    
    shadow.querySelector("#res").onclick =
    	() => this.display_results()
      
    this.enter_digit_input_mode()
    this.display_results()
  }
  
  enter_digit_input_mode() {
    if(this.mode == 'input_digit')
    	return
    
    this.mode = 'input_digit'
    this.decimal_place = -1
    this.display_screen(0)
  }
  
  display_screen(number) {
  	if(number == null)
    	number = this.screen_value
  
    this.screen_value = number
    this.scr.value = number
    if(this.decimal_place == 0)
    	this.scr.value += '.'
  }
  
  input_digit(dig) {
    this.enter_digit_input_mode()
    if(this.decimal_place == -1)
    	this.input_digit_before_decimal_separator(dig)
    else
    	this.input_digit_after_decimal_separator(dig)
  }
  
  input_digit_before_decimal_separator(dig) {
    this.display_screen(this.screen_value*10+dig)
  }
  
  input_digit_after_decimal_separator(dig) {
  	this.decimal_place++
    const to_add = Math.pow(10, -this.decimal_place)*dig
    this.display_screen(this.screen_value+to_add)
  }
  
  input_decimal_separator() {
    this.enter_digit_input_mode()
    if(this.decimal_place == -1)
    	this.decimal_place++
    this.display_screen()
  }
  
  input_addition(fun) {
  	if(this.mode == 'addition' || this.mode == 'displayed_results')
    	return
  
    this.mode = 'addition'
    
    this.addend = this.compute_addition_results()
    this.add_fun = fun
    this.factor = 1
    this.mul_fun = this.times
    this.display_screen(this.addend)
  }
  
  input_multiplication(fun) {
  	if(this.mode == 'multiplication' || this.mode == 'displayed_results')
    	return
    
    this.mode = 'multiplication'
    
    this.factor = this.compute_multiplication_results()
    this.mul_fun = fun
    this.display_screen(this.factor)
  }
  
  display_results() {
    this.finish_pending_operations()
    
    this.addend = 0
    this.add_fun = this.plus
    this.factor = 1
    this.mul_fun = this.times
    this.mode = 'displayed_results'
  }
  
  finish_pending_operations() {
    if(this.mode != 'addition')
      this.display_screen(this.compute_addition_results())
  }
  
  compute_addition_results() {
  	const mul_res = this.compute_multiplication_results()
  	if(this.addend != null && this.add_fun != null)
    	return this.add_fun(this.addend, mul_res)
  }
  
  compute_multiplication_results() {
    if(this.factor != null && this.mul_fun != null)
    	return this.mul_fun(this.factor, this.screen_value)
  }
}

customElements.define('simple-calc', SimpleCalc)
0

Uff, jakoś mi się udało. Poszło lepiej gdy dodałem więcej zmiennych, zapisywanie stanu operacji. Kod wyszedł jaki wyszedł i brakuje jeszcze wpisywania liczb zmiennoprzecinkowych. Poproszę o pomoc w refactoringu kodu.

document.addEventListener("DOMContentLoaded", 
    function() {
        var calcResult = 0;
        var firstArg = 0;
        var secondArg = 0;
        var clickOperationStatus = '';

        const buttonsIdNumber = 
        [
            'one', 'two', 'three', 'four', 'five', 
            'six', 'seven', 'eight', 'nine', 'zero'
        ];
        buttonsIdNumber.forEach(element => { 
            clickNumberToDisplay(element);
        });
        
        const displayValue = document.getElementById('main-display');

        if(clickOperationStatus === '') {
            const plusBtn = document.getElementById('plus');
            plusBtn.addEventListener('click', 
                function() {
                    firstArg = parseFloat(displayValue.value);
                    displayValue.value = '';
                    clickOperationStatus = 'sum';
                }
            );
            const minusBtn = document.getElementById('minus');
            minusBtn.addEventListener('click', 
                function() {
                    firstArg = parseFloat(displayValue.value);
                    displayValue.value = '';
                    clickOperationStatus = 'minus';
                }
            );
            const multiBtn = document.getElementById('multi');
            multiBtn.addEventListener('click', 
                function() {
                    firstArg = parseFloat(displayValue.value);
                    displayValue.value = '';
                    clickOperationStatus = 'multi';
                }
            );
            const divBtn = document.getElementById('divide');
            divBtn.addEventListener('click', 
                function() {
                    firstArg = parseFloat(displayValue.value);
                    displayValue.value = '';
                    clickOperationStatus = 'divide';
                }
            );
        }
        const resultBtn = document.getElementById('result');
        resultBtn.onclick = function() {
            switch(clickOperationStatus) {
                case 'sum':
                    secondArg = parseFloat(displayValue.value);
                    calcResult = firstArg + secondArg;
                    clickOperationStatus = '';
                    displayValue.value = calcResult;
                    break;
                case 'minus':
                    secondArg = parseFloat(displayValue.value);
                    calcResult = firstArg - secondArg;
                    clickOperationStatus = '';
                    displayValue.value = calcResult;
                    break;
                case 'multi':
                    secondArg = parseFloat(displayValue.value);
                    calcResult = firstArg * secondArg;
                    clickOperationStatus = '';
                    displayValue.value = calcResult;
                    break;
                case 'divide':
                    secondArg = parseFloat(displayValue.value);
                    calcResult = firstArg / secondArg;
                    clickOperationStatus = '';
                    displayValue.value = calcResult;
                    break;                         
                }
            }
        }
);
function clickNumberToDisplay(id) {
    const button = document.getElementById(id);
    button.addEventListener("click", 
        function() {
            const numberToDisplay = parseFloat(button.value);
            const display = document.getElementById('main-display');
            display.value += numberToDisplay; 
        }
    );
} 
1

Dałem radę z liczbami zmiennoprzecinkowymi:

function clickNumberToDisplay(id) {
    const button = document.getElementById(id);
    button.addEventListener("click", 
        function() {
            const numberToDisplay = parseFloat(button.value);
            const display = document.getElementById('main-display');
            if(isNaN(numberToDisplay)) {
                display.value += '.';
            } else {
                display.value += numberToDisplay;
            }
        }
    );
} 

1 użytkowników online, w tym zalogowanych: 0, gości: 1