Sejauh ini kita sudah mempelajari bagaimana cara menggunakan JavaScript pada HTML, bagaimana menuliskan sintaks JavaScript, mengenal tipe data dan fungsi sintaks yang ada, hingga akhirnya memanipulasi dan memberikan event pada elemen HTML melalui DOM Object.

Dengan komponen yang sudah disebutkan tadi, sepertinya sekarang kita sudah cukup bekal untuk memberikan “nyawa” pada Web Kalkulator kita sehingga dapat berfungsi layaknya sebuah kalkulator pada umumnya. Let’s do it!

Silakan buka project Web Kalkulator dengan editor favorit kita.


Jika Anda mengikuti seluruh latihan sebelumnya, maka struktur projek tampak seperti gambar di atas. Kita juga sudah mencoba menghubungkan berkas JavaScript (kalkulator.js) dengan berkas HTML (index.html) lalu menuliskan sintaks dasar untuk menampilkan pesan pada console browser.

Selanjutnya kita akan bekerja full pada kalkulator.js. Silakan hapus sintaks yang sudah kita buat sebelumnya.

1
console.log('Selamat Anda berhasil menggunakan JavaScript pada Website');

Langkah pertama adalah buatlah sebuah objek dengan nama calculator. Di dalamnya terdapat properti yang menggambarkan data dan kondisi dari kalkulatornya, seperti displayNumber, operator, firstNumber, dan isWaitForSecondNumber. Sehingga kodenya akan nampak seperti ini:

1
2
3
4
5
6
const calculator = {
  displayNumber: '0',
  operator: null,
  firstNumber: null,
  isWaitForSecondNumber: false,
};

Kita gunakan objek ini sebagai tempat menyimpan data dan kondisi pada calculator, di mana angka yang muncul pada layar kalkulator selalu diambil dari data calculator.displayNumber.

Nilai dari properti operator dan firstNumber diberikan null dulu karena akan diberikan nilai ketika pengguna melakukan aksi. Properti isWaitForSecondNumber merupakan kondisi di mana kalkulator sedang menunggu pengguna menentukkan angka kedua dalam melakukan perhitungan.

Setelah membuat object calculator, selanjutnya kita buat fungsi-fungsi umum yang dilakukan kalkulator seperti me-update angka pada layar dan menghapus data pada kalkulator.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
function updateDisplay() {
  document.querySelector('#displayNumber').innerText = calculator.displayNumber;
}
 
function clearCalculator() {
  calculator.displayNumber = '0';
  calculator.operator = null;
  calculator.firstNumber = null;
  calculator.isWaitForSecondNumber = false;
}

Lalu, kita buat juga fungsi untuk memasukkan angka ke dalam nilai displayNumber kalkulator.

1
2
3
function inputDigit(digit) {
  calculator.displayNumber += digit;
}

Kemudian, kita buat variabel buttons dengan menginisialisasikan nilai seluruh elemen button yang ada dan berikan event click pada tiap elemennya.

Untuk menangkap semua elemen div.button kita gunakan querySelectorAll("div.button") dan kita looping nilainya untuk diberikan event click di setiap elemen button-nya.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const buttons = document.querySelectorAll('.button');
 
for (const button of buttons) {
  button.addEventListener('click', function (event) {
    // mendapatkan objek elemen yang diklik
    const target = event.target;
 
    inputDigit(target.innerText);
    updateDisplay();
  });
}

Dengan demikian, keseluruhan kode di kalkulator.js akan tampak seperti berikut.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const calculator = {
  displayNumber: '0',
  operator: null,
  firstNumber: null,
  isWaitForSecondNumber: false,
};
 
function updateDisplay() {
  document.querySelector('#displayNumber').innerText = calculator.displayNumber;
}
 
function clearCalculator() {
  calculator.displayNumber = '0';
  calculator.operator = null;
  calculator.firstNumber = null;
  calculator.isWaitForSecondNumber = false;
}
 
function inputDigit(digit) {
  calculator.displayNumber += digit;
}
 
const buttons = document.querySelectorAll('.button');
for (const button of buttons) {
  button.addEventListener('click', function (event) {
    // mendapatkan objek elemen yang diklik
    const target = event.target;
    
    inputDigit(target.innerText);
    updateDisplay();
  });
}

Sekarang, kita coba jalankan index.html pada browser dan lihat fungsi kalkulator untuk yang pertama kali.


Uh, sangat aneh, bukan? Siapa yang ingin gunakan kalkulator seperti itu? Untuk saat ini tak apa. Setidaknya kode yang kita tuliskan sudah berhasil berjalan dengan baik. Selanjutnya kita akan memperbaiki keanehan-keanehan yang ada satu per satu.

Saat ini kalkulator masih dapat menampilkan angka 0 di awal bilangan, hal itu tentu aneh dan tidak pernah terjadi pada kalkulator manapun, kecuali menampilkan bilangan desimal. Untuk memperbaikinya, tambahkan sebuah kondisi dimana jika displayNumber bernilai ‘0’ di fungsi inputDigit() sehingga angka yang pertama dimasukkan pengguna akan menggantikan keseluruhan nilai displayNumber. Selain itu, lakukan seperti biasanya. Untuk melakukannya kita gunakan if-else statement.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
/* Kode lainnya disembunyikan */
 
function clearCalculator() {
  calculator.displayNumber = '0';
  calculator.operator = null;
  calculator.firstNumber = null;
  calculator.isWaitForSecondNumber = false;
}
 
function inputDigit(digit) {
  if (calculator.displayNumber === '0') {
    calculator.displayNumber = digit;
  } else {
    calculator.displayNumber += digit;
  }
}
 
const buttons = document.querySelectorAll('.button');
/* Kode lainnya disembunyikan */

Dengan demikian, kalkulator tidak akan menampilkan angka 0 diawal bilangan lagi.


Kemudian, kita akan membuat tombol clear (CE) pada kalkulator berjalan dengan semestinya sehingga kita tidak perlu melakukan reload pada browser untuk reset kalkulator seperti yang ditunjukkan GIF di atas.

Pada event handler, kita tambahkan kondisi dimana ketika event target merupakan elemen yang menerapkan class clear, kita akan panggil fungsi clearCalculator().

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
/* Kode lainnya disembunyikan */
 
const buttons = document.querySelectorAll('.button');
for (const button of buttons) {
  button.addEventListener('click', function(event) {
    // mendapatkan objek elemen yang diklik
    const target = event.target;
 
    if (target.classList.contains('clear')) {
      clearCalculator();
      updateDisplay();
      return;
    }
 
    inputDigit(target.innerText);
    updateDisplay();
  });
}

Kita bisa memanfaatkan event.classList untuk melihat nilai class apa saja dalam bentuk array yang ada di element target. Kemudian panggil function contains yang merupakan method dari array yang berguna untuk memastikan nilai yang berada di dalam array tersebut. Jika kondisi if terpenuhi, sudah dipastikan tombol tersebut adalah tombol clear (SE) sehingga kita perlu memanggil fungsi clearCalculator dan mengupdate display kalkulator.

Jangan lupa juga untuk gunakan return statement agar fungsi event handler terhenti sehingga kode yang ada di bawahnya tidak ikut tereksekusi.


Dengan demikian, keseluruhan kode pada kalkulator.js akan tampak seperti berikut.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
const calculator = {
  displayNumber: '0',
  operator: null,
  firstNumber: null,
  isWaitForSecondNumber: false,
};
 
function updateDisplay() {
  document.querySelector('#displayNumber').innerText = calculator.displayNumber;
}
 
function clearCalculator() {
  calculator.displayNumber = '0';
  calculator.operator = null;
  calculator.firstNumber = null;
  calculator.isWaitForSecondNumber = false;
}
 
function inputDigit(digit) {
  if (calculator.displayNumber === '0') {
    calculator.displayNumber = digit;
  } else {
    calculator.displayNumber += digit;
  }
}
 
const buttons = document.querySelectorAll('.button');
for (const button of buttons) {
  button.addEventListener('click', function(event) {
    // mendapatkan objek elemen yang diklik
    const target = event.target;
 
    if (target.classList.contains('clear')) {
      clearCalculator();
      updateDisplay();
      return;
    }
 
    inputDigit(target.innerText);
    updateDisplay();
  });
}

Selanjutnya, kita akan melengkapi beberapa fungsi lainnya yang ada pada kalkulator, yakni fungsi negative, operator, dan equals. Untuk itu, buat kondisi lainnya pada event handler sehingga kode tampak seperti berikut.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/* Kode lainnya disembunyikan */
 
const buttons = document.querySelectorAll('.button');
for (const button of buttons) {
  button.addEventListener('click', function (event) {
    // mendapatkan objek elemen yang diklik
    const target = event.target;
 
    if (target.classList.contains('clear')) {
      clearCalculator();
      updateDisplay();
      return;
    }
 
    if (target.classList.contains('negative')) {
      inverseNumber();
      updateDisplay();
      return;
    }
    if (target.classList.contains('equals')) {
      performCalculation();
      updateDisplay();
      return;
    }
    if (target.classList.contains('operator')) {
      handleOperator(target.innerText);
      return;
    }
 
    inputDigit(target.innerText);
    updateDisplay();
  });
}

Jika kita membukanya sekarang, error akan muncul ketika tombol-tombol fungsi dan operatornya ditekan.


Hal tersebut wajar karena kita belum mendefinisikan seluruh fungsi-fungsi yang kita dituliskan di atas. Mari kita deklarasikan fungsinya mulai dari inverseNumber().

1
2
3
4
5
6
function inverseNumber() {
  if (calculator.displayNumber === '0') {
    return;
  }
  calculator.displayNumber = calculator.displayNumber * -1;
}

Fungsi inverseNumber cukuplah simple. Hal tersebut karena kita hanya perlu melakukan perkalian calculator.displayNumber dengan nilai -1. Terkecuali jika displayNumber masih bernilai ‘0’, perkalian tidak akan dilakukan.


Sekarang tombol "+/-" sudah berfungsi dengan baik.

Selanjutnya, kita akan membuat fungsi untuk menetapkan sebuah operator, baik itu "+" atau "-" di kalkulator. Tuliskan fungsi berikut.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function handleOperator(operator) {
  if (!calculator.isWaitForSecondNumber) {
    calculator.operator = operator;
    calculator.isWaitForSecondNumber = true;
    calculator.firstNumber = calculator.displayNumber;
 
    // mengatur ulang nilai display number supaya tombol selanjutnya dimulai dari angka pertama lagi
    calculator.displayNumber = '0';
  } else {
    alert('Operator sudah ditetapkan');
  }
}

Fungsi tersebut membutuhkan satu buah argument, yaitu operator. Nilai operator tersebut bersumber dari innerText tombol operator yang menjadi event target. Secara prinsip, fungsi ini bertujuan untuk menyimpan operator dan firstNumber dengan nilai displayNumber saat ini pada object calculator, hanya jika properti isWaitForSecondNumber bernilai false. Namun, jika isWaitForSecondNumber bernilai true, browser akan menampilkan alert dengan pesan “Operator sudah ditetapkan”.

Voila! Sekarang tombol operator sudah dapat menetapkan nilai operator pada object calculator.


Kita bisa lihat di console browser bahwa nilai sekarang dari properti operator dan firstNumber tidak null lagi, begitu pula dengan properti isWaitForSecondNumber yang sudah berubah menjadi true.

Kita buat fungsi terakhir, yaitu performCalculation. Fungsi ini digunakan untuk melakukan kalkulasi terhadap nilai - nilai yang terdapat pada objek calculator, sehingga pastikan kalkulator sudah memiliki nilai operator dan firstNumber ketika fungsi ini dijalankan.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
function performCalculation() {
  if (calculator.firstNumber == null || calculator.operator == null) {
    alert('Anda belum menetapkan operator');
    return;
  }
 
  let result = 0;
  if (calculator.operator === '+') {
    result = parseInt(calculator.firstNumber) + parseInt(calculator.displayNumber);
  } else {
    result = parseInt(calculator.firstNumber) - parseInt(calculator.displayNumber);
  }
 
  calculator.displayNumber = result;
}

Fungsi tersebut diawali dengan pengecekan nilai-nilai yang dibutuhkan untuk melakukan kalkulasi. Jika tidak terpenuhi maka proses akan dihentikan. Namun jika terpenuhi kalkulasi akan dilakukan.

Dalam melakukan kalkulasi terdapat pengecekan tipe operator apa yang akan dilakukan. Kita juga menggunakan parseInt() untuk mengubah nilai string menjadi number. Mengapa konversi tipe data dibutuhkan? Sejatinya kita menggunakan string dalam menampilkan nilai pada jendela browser, namun untuk proses kalkulasi kita membutuhkan number.

Dengan demikian, seluruh struktur kode pada berkas kalkulator.js akan tampak seperti berikut.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
const calculator = {
  displayNumber: '0',
  operator: null,
  firstNumber: null,
  isWaitForSecondNumber: false,
};
 
function updateDisplay() {
  document.querySelector('#displayNumber').innerText = calculator.displayNumber;
}
 
function clearCalculator() {
  calculator.displayNumber = '0';
  calculator.operator = null;
  calculator.firstNumber = null;
  calculator.isWaitForSecondNumber = false;
}
 
function inputDigit(digit) {
  if (calculator.displayNumber === '0') {
    calculator.displayNumber = digit;
  } else {
    calculator.displayNumber += digit;
  }
}
 
function inverseNumber() {
  if (calculator.displayNumber === '0') {
    return;
  }
  calculator.displayNumber = calculator.displayNumber * -1;
}
 
function handleOperator(operator) {
  if (!calculator.isWaitForSecondNumber) {
    calculator.operator = operator;
    calculator.isWaitForSecondNumber = true;
    calculator.firstNumber = calculator.displayNumber;
    calculator.displayNumber = '0';
  } else {
    alert('Operator sudah ditetapkan');
  }
}
 
function performCalculation() {
  if (calculator.firstNumber == null || calculator.operator == null) {
    alert('Anda belum menetapkan operator');
    return;
  }
 
  let result = 0;
  if (calculator.operator === '+') {
    result = parseInt(calculator.firstNumber) + parseInt(calculator.displayNumber);
  } else {
    result = parseInt(calculator.firstNumber) - parseInt(calculator.displayNumber);
  }
 
  calculator.displayNumber = result;
}
 
const buttons = document.querySelectorAll('.button');
for (const button of buttons) {
  button.addEventListener('click', function (event) {
    // mendapatkan objek elemen yang diklik
    const target = event.target;
 
    if (target.classList.contains('clear')) {
      clearCalculator();
      updateDisplay();
      return;
    }
 
    if (target.classList.contains('negative')) {
      inverseNumber();
      updateDisplay();
      return;
    }
 
    if (target.classList.contains('equals')) {
      performCalculation();
      updateDisplay();
      return;
    }
 
    if (target.classList.contains('operator')) {
      handleOperator(target.innerText)
      return;
    }
 
    inputDigit(target.innerText);
    updateDisplay();
  });
}

Jika kita buka index.html sekarang, seharusnya kalkulator sudah dapat melakukan kalkulasi.


Catatan:

Aplikasi kalkulator yang telah kita buat tidak bisa melakukan operasi aritmatika secara berkelanjutan, yaitu melakukan kedua secara langsung tepat setelah operasi pertama selesai. Anda bisa mengembangkannya lebih lanjut untuk meningkatkan kemampuan problem solving yang lebih baik.

Selamat! Sejauh ini kita sudah bisa membuat aplikasi web dengan memanfaatkan pengetahuan yang sudah kita pelajari. Selanjutnya kita akan mengenal salah satu Web API yang menarik untuk diterapkan pada project kalkulator kita.


Sebelumnya : Manipulasi DOM Selanjutnya : Web Storage